angular.min.js:63 ReferenceError - javascript

Am getting following error when use a factory into angular module
i have factory module like below
angular.module('pollServices', ['ngResource']).factory('Poll', function($resource) {
return $resource('polls/:pollId', {}, {
query: { method: 'GET', params: { pollId: 'polls' }, isArray: true }
})
});
I have another module called polls in the same file, i need to use the factory module to this app so i have called it in module config like
angular.module('polls', ['pollServices'])
When i call the factory inside this module like
function PollListCtrl($scope) {
$scope.polls = Poll.query();
}
am getting error like
angular.min.js:63 ReferenceError: Poll is not defined
at new PollListCtrl (app.js:29)

you didn't call the Poll factory from PollListCtrl
function PollListCtrl(Poll,$scope) {
$scope.polls = Poll.query();
}

You have to inject pollServices to the controller.
angular.module('polls', ['pollServices'])
.controller('PollListCtrl', PollListCtrl)
PollListCtrl.$inject = ["$scope", "pollServices"];
function PollListCtrl($scope, Poll) {
$scope.polls = Poll.query();
}

Related

Unit Testing a Keycloak-enabled Angular app

I'm trying to write a test suite for an Angular app that uses Keycloak for authentication.
However, as Keycloak requires you to manually bootstrap Angular and set up a few interceptors, I'm unable to fire any test due to the following error:
Error: $injector:unpr
Unknown Provider: AuthProvider <- Auth <- authInterceptor <- $http <- $templateRequest <- $route
This is the code for the interceptor that raises the error:
angular.module('MPMReportGenerator')
.factory('authInterceptor', function authInterceptor ($q, Auth, $log) {
return {
request: function (config) {
var deferred = $q.defer()
Auth.updateToken(5).success(function () {
config.headers = config.headers || {}
config.headers.Authorization = 'Bearer ' + Auth.token
deferred.resolve(config)
}).error(function () {
deferred.reject('Failed to refresh token')
})
$log.info(deferred.promise)
return deferred.promise
}
}
})
My thinking is that I should mock the interceptor and just have it return the request.
However, I fail to see how I could do that, since this interceptor is never injected anywhere as a dependency, it's simply declared with the block above and that's it. My understanding of mocked services is that they need to be injected somewhere to be mocked.
My implementation of Keycloak into Angular comes straight from their examples, if that helps.
Edit
I've been trying to inject a mocked Auth module into the service I'm writing a test for, but still no change.
I'm very new to unit testing in general, so I'm a bit lost trying to track this down. I feel like I know where the issue is, but not how to solve it (The Auth service is added during the bootstrap of the app, I need to mock it for things to work, but it seems I don't know how/where to mock it properly)
Here's the whole testing code:
describe('Services', function () {
'use strict'
beforeEach(module('MPMReportGenerator'))
module(function ($provide) {
$provide.factory('Auth', function () {
return null
})
})
var sectionService, $httpBackend, mockAuth
beforeEach(inject(function (_sectionService_, _$httpBackend_, Auth) {
sectionService = _sectionService_
$httpBackend = _$httpBackend_
mockAuth = Auth
}))
it('should get sections', function () {
$httpBackend.expect('GET', '/MPMReportGenerator/api/categories/all').respond(200)
sectionService.getSections()
expect($httpBackend.flush).not.toThrow()
})
})
Edit 2
I've managed to get past my initial error by making a mock version of Auth.
I am now facing issues implementing a mock version of Keycloak's Javascript library.
My current mock code is as follow:
beforeEach(module(function ($provide) {
$provide.factory('Auth', function ($q) {
return {
updateToken: function (minValidity) {
return {
success: function (fn) {
var deferred = $q.defer()
deferred.resolve('')
fn(deferred.promise)
},
error: function (fn) {
var deferred = $q.defer()
deferred.resolve('Error')
fn(deferred.promise)
}
}
},
token: 'thisisafaketokenfortesting'
}
})
}))
And throws this error:
Expected function not to throw, but it threw TypeError: undefined is not an object (near '...}).error(function () {...').
target/MPMReportGenerator-1.0.0/js/app.service.spec.js:42:43
loaded#http://localhost:9876/context.js:151:17
My actual test is this:
it('should get sections', function () {
$httpBackend.expect('GET', '/MPMReportGenerator/api/categories/all').respond(200)
sectionService.getSections()
expect($httpBackend.flush).not.toThrow()
})
I finally figured it out.
Here is the needed code if anyone wants to test an Angular app with keycloak:
beforeEach(
module(function ($provide) {
$provide.factory('Auth', function ($q) {
return {
updateToken: function (minValidity) {
return {
success: function () {
return {
error: function () {
var deferred = $q.defer()
return deferred.promise
}
}
}
}
},
token: 'thisisafaketokenfortesting'
}
})
}))
Note that you will likely need to mock other parts of the keycloak library if you intend to test the interceptors provided in the official examples.
Edit
Don't use the code above, the following works much better:
$provide.factory('Auth', function () {
return {
updateToken: function (minValidity) {
return {
success: function () {
return this
},
error: function () {
return this
}
}
},
token: 'thisisafaketokenfortesting'
}
})

Unknown provider: $resourceProvider Error when calling angular service from outer js method

I'm trying to retrieve a value from an angular service in a function outside my angular app. The service looks like this:
angular.module('myApp.services').factory('MyService', [ '$resource', function ($resource) {
return {
getModuleId: function() {
return $resource('/api/module_id', {}, {
query: {
method: 'GET'
}});
}
}
}]);
Then in an html file, inside a <script> tag, I use the following code to call it:
$(document).ready(function() {
...
moduleId = angular.injector(['ng', 'myApp.services']).get("MyService").getModuleId();
...
})
But this throws the error mentioned in the title:
Error: [$injector:unpr] Unknown provider: $resourceProvider <- $resource <- MyService
If I remove '$resource' from the Service (therefore the service has no injections) the error disappears. But I need to make it work with the injection there.
You forgot to include the module ngResource
angular.module('myApp.services',[ngResource]).factory('MyService', [ '$resource', function ($resource) {
return {
getModuleId: function() {
return $resource('/api/module_id', {}, {
query: {
method: 'GET'
}});
}
}
}]);

How use inside common provider $http in Angular 1.4?

I try to use common provider and in angular app config function set data in provider.
.provider('userData', function() {
var authUser = {};
return {
checkUser: function() {
// wish to able use $http here for request to get data from service
// save all data into 'authUser' object
// $get return 'authUser' object
},
getCookie: function(value) {
// wish to able use $http here
},
$get: function() {
// only for return object
return authUser;
}
}
})
app.config(['userDataProvider', function(userDataProvider) {
userDataProvider.checkUser();
});
.controller('headerCtrl', ['$scope', 'userData', '$http', function($scope, userData, $http) {
// use inside all controllers/directives 'userData'
});
I try to use $http as parameter in $get function -> not working: error:
$get: function($http) {
return authUser;
}
Also I can't find any valid example for using $http inside provider. Inside service/factory $http work fine, but I need to prepare data in provider from config function.
Services, factory & value aren't available at config phase by design.
You could do it in run()
app.run(['userData', function(userData) {
userData.checkUser();
});

How to call a function from another module

In my angularJS application, I have two modules : module A and module B.
angular.module('A').controller('ACtrl',function($scope){
$scope.alertA = function(){alert('a');}
//...
});
angular.module('B').controller('BCtrl',function($scope){
//...
});
How to call the function alertA in the module B ?
You need to define a factory in module A:
var moduleA= angular.module('A',[]);
moduleA.factory('factoryA', function() {
return {
alertA: function() {
alert('a');
}
};
});
Then use the alertA factory in module B:
angular.module('B',['A']).controller('BCtrl',function($scope,'factoryA'){
factoryA.alertA();
});
Refactor your code in following these steps:
Define a service in module A
Add module A as dependency to module B
Inject the service into the controller
Here is an example:
angular.module('A').service('API', function ($http) {
this.getData = function () { return $http.get('/data'); };
});
angular.module('B', ['A']).controller('dashboardCtrl', function ($scope, API) {
API.getData().then(function (data) { $scope.data = data; });
});

AngularJS testing a service

I'm trying to test a simple service but I'm getting an Unkown Provider error. Here is the service definition:
var sessionManager = angular.module('MyApp.SessionManager', ['ngResource']);
sessionManager.factory('UserService', function($resource) {
var UserService = $resource('/api/users/:key', {}, {
getNewUUID: {
method: 'GET',
params: {
action: 'getNewUserUUID'
}
}
});
return UserService;
});
and here is the test:
describe('Testing SessionManager', function() {
var userService;
beforeEach(function() {
module('MyApp.SessionManager');
inject(function($injector) {
userService = $injector.get('UserService');
});
});
it('should contain a UserService', function() {
expect(userService).toBeDefined();
});
});
I can't seem to see the problem, I know that the UserService javascript file is being called because I can get a console log at the top of the file, however if I put it in the service definition I don't see it get called. So for some reason it's like Angular is not instantiating my service?
I realized that the problem was my module MyApp.SessionManager was being replaced because I thought you could declare dependencies every time it was reopened to add a module. The code above is fine if of course the service is actually surviving up until the tests.

Categories