Trying to test a factory and I am having injection issues - angularjs

I am rather new to angular and testing in general. I am trying to set up a basic test where I see if the object is defined before I start trying to test anything else.
I am getting this error:
Error: [$injector:unpr] Unknown provider: $stateParamsProvider <-
$stateParams <- Form
However when I try and do this basic test on other test files this error does not show up.
Factory
angular.module('omnibyte_inspect_web.objects')
.factory('CommonQuestions', ['common_questions_factory', 'Form', '$rootScope',
function (common_questions_factory, Form, $rootScope) {
// Ctor
function CommonQuestions(data) {
var keys = Object.keys(data);
for (var i = 0; i < keys.length; i++) {
this[keys[i]] = data[keys[i]];
}
};
CommonQuestions.prototype.Select = function () {
this.Id = guid();
Form.CurrentForm().AddCommonQuestion(angular.copy(this));
};
CommonQuestions.prototype.Remove = function () {
common_questions_factory.delete(this.Id).then(function () {
window.location.reload();
});
};
// Static Methods
CommonQuestions.Current = function () {
return $rootScope.config_info;
};
CommonQuestions.GetAll = function (callback) {
common_questions_factory.get().then(function (data) {
var collection = [];
for (var i = 0; i < data.length; i++) {
collection.push(new CommonQuestions(data[i]));
}
callback(collection);
});
};
return CommonQuestions;
}]);
Test File
describe('CommonQuestions Test', function () {
beforeEach(module('omnibyte_inspect_web.objects'));
var common_questions_factory, $rootScope, CommonQuestions, Form;
beforeEach(inject(function (_common_questions_factory_, _Form_, _$rootScope_, _CommonQuestions_) {
common_questions_factory = _common_questions_factory_;
Form = _Form_;
$rootScope = _$rootScope_;
CommonQuestions = _CommonQuestions_;
spyOn(CommonQuestions, 'GetAll');
spyOn(common_questions_factory, 'get');
spyOn(CommonQuestions, 'Current');
}));
it('should have CommonQuestions be defined', function () {
expect(CommonQuestions).toBeDefined();
});
});
Edit
Having the same issue on multiple files, but it seems to be coming from my Form file. Which is:
Form
angular.module('omnibyte_inspect_web.objects')
.factory('Form', ['forms_factory', 'authentication_service', 'common_questions_factory', 'formdata_factory', 'missinginformation_factory', '$stateParams', 'Question', 'LocationContact', '$rootScope', '$ionicPopup', '$state',
function (forms_factory, authentication_service, common_questions_factory, formdata_factory, missinginformation_factory, $stateParams, Question, LocationContact, $rootScope, $ionicPopup, $state) {
Second Edit
After putting this module beforeEach(module('ui.router')); in my test file I get:
Error: [$injector:unpr] Unknown provider: $ionicPopupProvider <-
$ionicPopup <- Form
After putting this module beforeEach(module('$ionic')); in my test file I get the errors to go away; however, I get Expected undefined to be defined. This test has worked in all of my other files.

$stateParams is a service in angular-ui/ui-router. make sure ui-router is included in your karma.conf.js files.

Found the solution. I needed to add these modules to the test file:
beforeEach(module('omnibyte_inspect_web.objects'));
beforeEach(module('ui.router'));
beforeEach(module('ionic'));
And in my karma.conf.js file this was commented out:
'www/lib/ionic/js/ionic.bundle.js',
After making those changes it was fixed.

Related

Angular Service injected not working

I have created and injected the service(myService) into my app (app) , but it is not working. The error implies that I have not defined the service anywhere:
Error: [$injector:unpr] Unknown provider: myServiceProvider <- myService <- myController
myService calls another service - ajaxService to do the actual http call.
The only reason I would think that myService throws the above error when trying to call it in myController is because I have another module defined in the app definition (common.components). This module has its own separate services which I am using elsewhere in my app. I am wondering if the app is searching for a definition of myService within that the common.components module instead of inside itself.
Here is my code:
- app.js
var app = angular.module('app ', ['ngRoute','common.components']);
- myService.js
var serviceId = 'myService';
angular.module('app').service(serviceId,['$q','ajaxService','$log',myService]);
function myService($q, ajaxService, $log){
var states = [];
this.getStates = function() {
var defered = $q.defer();
ajaxService.getStates().then(function(result){
states = result.data;
defered.resolve(states);
},
function(error){
deferred.reject();
});
return defered.promise;
};
}
- ajaxService.js
var serviceId = 'ajaxService';
angular.module('app',[]).service(serviceId,['$http','$log',ajaxService]);
function ajaxService($http,$log){
this.getStates = function() {
return $http.get('./json/DATA.json');
};
}
myController.js
(function(){
'use strict';
angular.module('app').controller('myController',['$scope','$log','myService',myController]);
function myController($scope,$log,myService){
$scope.states = [];
myService.getStates().then(function(states){
$scope.states = states;
});
}
})();
I have been trying to find out what is wrong for hours, but I am lost. Can someone help me with this?
I have updated my answer as you have now provided more info.
Your issue is in your ajaxService.js
Change this line
angular.module('app',[]).service(serviceId,['$http','$log',ajaxService]);
to this
angular.module('app').service(serviceId,['$http','$log',ajaxService]);
Your are recreating the app module by adding the [].

Trying to test an angular controller with jasmine - errors

I am very new to angular/jasmine/karma and I'm having trouble getting a test written for my controller. The test itself is running successfully, but in the test running I'm getting the following error:
Error: userFactory() method does not exist
userFactory() is a method call made in my controller to a service that returns a promise. I'm not sure how to make sure this is correctly defined in the test.
Here is my code:
app.js
(function () {
angular.module('mdotTamcCouncil', ['mdotTamcCouncil.core', 'blurb']);
angular.module('mdotTamcCouncil.core', []);
})();
blurb-service.js
(function () {
angular.module('mdotTamcCouncil.core').factory('blurbsFactory', function ($http) {
var promise = null;
return function () {
if (promise) {
// If we've already asked for this data once,
// return the promise that already exists.
return promise;
} else {
promise = $http.get(jsGlobals.blurbsDataURL);
return promise;
}
};
});
})();
user-service.js
(function () {
angular.module('mdotTamcCouncil.core').factory('userFactory', function ($http) {
var promise = null;
return function () {
if (promise) {
// If we've already asked for this data once,
// return the promise that already exists.
return promise;
} else {
promise = $http.get(jsGlobals.userDataURL);
return promise;
}
};
});
})();
blurb-controller.js
(function () {
angular.module('blurb')
.controller('BlurbController', ['$scope', 'blurbsFactory', 'userFactory', function ($scope, blurbsFactory, userFactory) {
$scope.content = "";
$scope.blurbs = {};
$scope.currentUser = {};
this.editMode = false;
userFactory().success(function (data) {
$scope.currentUser = data;
});
blurbsFactory().success(function (data) {
$scope.blurbs = data;
$scope.content = $scope.blurbs[$scope.textKey];
});
this.enterEditMode = function () {
this.editMode = true;
};
this.saveEdits = function () {
this.editMode = false;
$scope.blurbs[$scope.textKey] = $scope.content;
};
}]);
})();
blurb-module.js
(function () {
'use strict';
angular.module('blurb', ['ngSanitize', 'mdotTamcCouncil.core']);
})();
and my test spec:
describe('BlurbController', function () {
var scope, controllerService;
beforeEach(module('mdotTamcCouncil'));
beforeEach(module('mdotTamcCouncil.core'));
beforeEach(module('blurb'));
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
controllerService = $controller;
}));
it("should get 'user' from 'data/user.json'", inject(function ($httpBackend) {
$httpBackend.expectGET("data/user.json").respond({"userName": "myera","email": "something#something.com","isAdmin": true});
$httpBackend.expectGET("data/blurbs.json").respond('{"mainPageIntro": "<h2>Welcome</h2>"}');
ctrl = controllerService('BlurbController', { $scope: scope });
$httpBackend.flush();
expect(scope.currentUser).toEqual({"userName": "myera","email": "something#something.com","isAdmin": true});
expect(scope.blurbs).toEqual({ "mainPageIntro": "<h2>Welcome</h2>" });
}));
});
I've pieced this together from reading blogs and stackoverflow answers. I'm not sure that I'm even doing it correctly.
The tests themselves actually pass, but I am getting the error in the console about the missing "userFactory()" method. I assume I would also get the message for the "blurbFactory()" method if it was getting that far. I don't believe I can test the actual functionality of the controller without first resolving these errors.
What am I doing wrong? Thanks so much for any help you can provide.
I believe the issue you are seeing is because you didn't include the 'mdotTamcCouncil.core' module as a dependency in the blurb module. When defining it, you should be able to pass in a list of dependencies using
angular.module('blurb', ['mdotTamcCouncil.core']);
You are only getting the one console error because the execution stops when the userFactory() fails. I'm not sure why the tests are showing as passing, it should pick up the exceptions and fail - could be an oddity with your chosen test runner.

Unknown provider in .config() with custom Provider

I've got this in app.js:
angular.module('App',[]).config(['TranslationProvider', function (TranslationProvider) {
//codes...
}]);
And this service in another file:
angular.module('App')
.provider('Translation', function() {
var translations = {foo:"bar"}
this.$get = function(){
return translations;
};
});
No 404 error with the service js file, but when angular injector try to instantiate it gives me this error:
Uncaught Error: [$injector:modulerr] Failed to instantiate module App due to:
Error: [$injector:unpr] Unknown provider: TranslationProvider
I've followed the angjs documentation https://docs.angularjs.org/guide/providers
It seems to be a bug in Angular 1.2.x. The order of the calls matter. When you call provide before config it works. It also works with Angular 1.3.x regardless of the order.
You are almost there.
First the config:
angular.module('App')
.config(["TranslationProvider", function(theProvider) {
console.log("in config" + theProvider)
theProvider.setName("some name");
}]);
The error you were having was due to you using the constructor function as an argument.
Now your provider:
angular.module('App')
.provider('Translation', function TranslationProvider() {
var translations = {foo:"bar", name:""};
var dynamicName;
this.setName = function(configName) {
dynamicName = configName;
};
this.$get = function(){
translations.name = dynamicName;
return translations;
};
});
Also note that an anonymous function (i.e. .provider('Translation', function () {) could also have been used and the code would have worked just as well.
Using it all in a controller:
angular.module('App')
.controller('MyController', [
'$scope',
'Translation',
function ($scope,
translationProvider) {
$scope.modal = {};
$scope.projects = [];
console.log(translationProvider)
$scope.foo = translationProvider;
}]);

Angularjs injecting factory with http to a controller

I keep getting errors while injecting a factory in to a controller. It worked in a case where the controller is simple. It fails when the page and the controller has special components like ng-flow or ng-grid.
var carouselController = carouselApp.controller('carouselController', ['CMSFactory', function ($scope,CMSFactory) {
// MY CODE HERE...
}
var CMSServices = angular.module('api.services', [ 'ngResource' ]);
CMSServices.factory('CMSFactory', function($http, $q) {
var CMSService = {};
CMSService.saveSiteInfo = function(data) {
// MY CODE HERE...
};
CMSService.addSlide = function(data) {
// MY CODE HERE...
};
return CMSService;
});
I get TypeError: undefined is not a function error. If I remove the factory injection code works fine.
Appreciate any help...
You're not declaring $scope in your array of dependencies:
Change:
var carouselController = carouselApp.controller('carouselController', ['CMSFactory', function ($scope,CMSFactory) {
To:
var carouselController = carouselApp.controller('carouselController', ['$scope', 'CMSFactory', function ($scope,CMSFactory) {

AngularJS use custom services in custom providers

I have a simple question about the dependency injection in Angular. I create custom services in order to use them within each other. Unfortunately I receive errors the way I was trying it. This is my Code:
var myApp = angular.module('app', []);
myApp.service('$service1', ['$rootScope', function($rootScope) {
this.test = function() {
console.log('service1');
};
}]);
myApp.provider('$service2', ['$service1', function($service1) {
var service = 'service2';
this.registerService = function(mytext) {
service = mytext;
};
this.$get = function() {
var that = {};
that.test = function() {
console.log(service);
};
return that;
};
}]);
myApp.config(['$service2Provider', function($service2Provider) {
$service2Provider.registerService('changed service2');
}]);
myApp.controller('AppCtrl', ['$rootScope', '$service1', '$service2',
function($rootScope, $service1, $service2) {
$service1.test();
$service2.test();
}]);
Error: [$injector:modulerr] Failed to instantiate module app due to:
[$injector:unpr] Unknown provider: $service1
http://errors.angularjs.org/1.2.0-rc.2/$injector/unpr?p0=%24service1
If you remove the dependency of $servic1 in $service2 it will work, but why?
The code is mostly right, except you have to inject service dependencies in $get, not in the provider constructor function, like this:
myApp.provider('$service2', function() {
var service = 'service2';
this.registerService = function(mytext) {
service = mytext;
};
this.$get = ['$service1', function($service1) {
var that = {};
that.test = function() {
console.log(service);
};
return that;
}];
});
It appears that provider can not inject such a dependency. If you rewrite $service2 using a factory, it works:
myApp.factory('$service2', ['$service1', function($service1) {
var that = {};
that.test = function() {
$service1.test();
console.log('service2');
};
return that;
}]);
See this plunker: http://plnkr.co/edit/JXViJq?p=preview
Also I believe that service names starting with a $ a reserved for AngularJS and its extensions. Use names without the $ at the beginning for services defined by your application.

Resources