Unit test, function in Angularjs Controller - angularjs

I have a controller with a function and a promise and I've had a lot of problems testing it with jasmine and karma, please help! This is my service:
primaryDistributionApp.factory('gridData_Factory', ['$resource', function ($resource) {
return {
realTime:
$resource('/RealTime/', {},
{
"listAll": { method: "GET", params: {}, isArray: true }
}
)
};
}]);
And this is part of my controller (called gridInfo_Ctrl):
$scope.getData = function (){
gridData_Factory.realTime.listAll().$promise.then(function (data) {
$scope.data = data;
})
}
$scope.getData();
I'm trying to make a test in order to know if scope.data is Defined!

grab any dom element related to the controller, get its scope and test for Data.
var scope=angular.element($('cssquery')).scope();
i don't remember jasmine sintax correctly but would be something like
expect(scope.data).not.to.be.truthy;
and there you can perform several tests in your scope/

Related

AngularJs, calling a $resource from within an Interceptor

I have just about given up with this. But I have a $resource that uses a query() to retrieve a list of items. I then have an Interceptor that runs over those items in order to insert an $interval.
The $interval at a specific point will then get an item again using the $resource's get() function. But its this get() that is not working.
The call happens but I cannot get the response back into the template.
myServices.factory('Items', ['$resource',
function($resource) {
return $resource("/items", {}, {
'query': {
interceptor: MyInterceptor,
url: "/items",
isArray: true
},
})
}]);
myServices.factory('MyInterceptor', function($q, $interval, $injector, $rootScope) {
return {
'response': function(response) {
angular.forEach(response.resource, function (item) {
$interval(function () {
item.something = 1 + item.something;
if(item.something == 10)
{
item = $injector.get("Mine").get({slug: item.id});
}
});
});
return response;
}
};
});
I thought that this line item = $injector.get("Mine").get({slug: item.id}); would work, but it doesn't. The new item is not changed in the template.
So I changed it to something like this, which did not work either;
$injector.get("Mine").get({slug: item.id}, function(data){
item = data;
});
I have tried with $q and $promise too, but I had no luck with those either. Finding decent examples on those subjects was tough too.
In short ...... I am using an Interceptor inside a $resource, with an $interval which then needs to eventually change a single value within an array of values within the $scope - how can I get this to work?
In short ...... I am using an Interceptor inside a $resource, with an $interval which then needs to eventually change a single value within an array of values within the $scope - how can I get this to work?
Based on the above statement I will give an answer.
First things first, remove the interceptor. You won't need it. Instead use a service.
Write a service called ProcessedItems.
angular.module('app')
.service('ProcessedItems', ['Items', '$q', function(Items, $q){
return {
query: function() {
var defer = $q.defer();
Items.query()
.$promise
.then(function(response){
angular.forEach(response.resource, function(i)){
i.s = 1 + i.s;
if(i.s == 10) {
i = $injector.get("Mine").get({slug: i.id});
i.$promise.then(function(){
defer.resolve(response);
}, function(){
defer.reject();
});
};
};
});
return defer.promise;
}
};
}]);
After this service is set up, in your controller you can do
angular.module('app')
.controller('AppController', ['$scope', 'ProcessedItems',
function($scope, ProcessedItems){
$scope.items = [];
ProcessedItems.query().then(function(pitems){
$scope.items = pitems;
});
});
What this will essentially do is first process the data completely and then display it in the view.

How to access $scope from $resource

I need to splice an array on success. How do I call back out to my $scope.list in order to remove an item from the list array? Is that how I should do it or is there a better way? Like bubbling an "update" or something?
var phonecatServices = angular.module('phonecatServices', ['ngResource']);
var urlBase = 'http://example.com/api/';
function resourceErrorHandler(response) {
console.log("error");
}
function resourceResponseHandler(response) {
console.log($scope.list);
$scope.list.data.splice(index, 1);
console.log("success");
}
phonecatServices.factory('api_resource', ['$resource',
function($resource){
return $resource(urlBase+':api_resource/:id.json', {}, {
query: {method:'GET', isArray:false},
save:{method:'POST', isArray:false},
delete:{method:'DELETE', isArray:false, interceptor:{response:resourceResponseHandler, responseError:resourceErrorHandler}},
});
}]);
Make $scope an argument in the functions and pass it with the method call in the controllers, or bundle it in the response object.

Angularjs: Pass parameter from controller to factory

I have following code in service
define(['./module'], function(services) {
'use strict';
services.factory('user_resources', ['$resource', '$location', function($resource, $location) {
return $resource("", {},
{
'testService':{method:"GET",url:'http://11.11.11.11/url/index.php?data={method:method_name,params:{param1:value,param2:value,}}',isArray:true}
});
}]);
});
from controller i am calling this factory method how to pass parameters to this testService from controller?
following is code in controller to call this factory
user_resources.testService().$promise.then(function(data) {
console.log("****************************");
console.log(data);
$scope.mylist=data;
});
Thats not how $resource works.
$resource("http://11.11.11.11/url/index.php",
{'testService':{method:"GET",url:'http://11.11.11.11/url/index.php',isArray:true}})
Then you call it with:
var theObjToSend = {
method:method_name,
params:
{
param1:value,
param2:value
}
};
new user_resources({data: theObjToSend}).testService();
or
user_resources.testService({data: theObjToSend});
Its going to serialize the object so it might look weird. Any reason why you dont use query parameters?
e.g.
?method=method_name&params={param1:value,param2:value}
You should really check this vid: https://egghead.io/lessons/angularjs-using-resource-for-data-models
return $resource("http://11.11.11.11/url/index.php");

AngularJS factory not working

I have abstracted my working code from a controller into a factory, but it doesn't seem to be working and I can't find what's wrong. I opted for a factory rather than a service because I wanted to execute some code that defined the variable before returning that variable; I want to get result.station (a part of the data returned by the API), not the full result.
This is my code:
var app = angular.module("myApp", []);
app.factory('api', ['$http',
function($http) {
var station_list = [];
$http({
method: 'GET',
url: 'http://api.irail.be/stations/?format=json&lang=nl'
})
.success(function(result) {
station_list = result.station;
});
return {
Stations: function() {
return station_list;
}
};
}
]);
app.controller("myController", ['api', '$scope',
function(api, $scope) {
$scope.station_list = api.Stations();
$scope.title = "Stations";
}
]);
and a working example.
Try this:
.success(function(result) {
angular.copy(result.station, station_list);
});
You had a small error, you were replacing the array instead of populating it. I used angular.copy instead of the assignment in your factory and it works
http://plnkr.co/edit/sqgKcFZAcClmkfdXHhrz
The problem is that you are dealing with asynchronous nature of AJAX.
I would suggest to have a delegate method in controller, which will be called when the service call is complete.
Something like the following:
app.controller("myController", ['api', '$scope',
function(api, $scope) {
api.Stations( function(station_list) {
$scope.station_list = station_list;
});
$scope.title = "Stations";
}
]);
The following is a service method excerpt:
return {
Stations: function(delegate) {
if (delegate)
delegate(station_list);
return station_list;
}
};

Can I have multiple functions in my AngularJS Factory?

I'm following the Tutorial from the official AngularJS docs and I want to know if I can add another function to the Phone factory so that I can organize code better. They have declared a "query" function, but what if I wanted to add a query2 function that references a different url...say phones2/:phoneName.json for example?
Factory declaration:
var phonecatServices = angular.module('phonecatServices', ['ngResource']);
phonecatServices.factory('Phone', ['$resource',
function($resource){
return $resource('phones/:phoneId.json', {}, {
query: {method:'GET', params:{phoneId:'phones'}, isArray:true}
});
}]);
I have tried a number of things and non of them seem to be working :s
This answer seems to be on the right track, but the syntax for each factory function doesn't quite match up with the above factory.
Something along the lines of:
phonecatServices.factory('Phone', ['$resource',
function($resource){
return {
query: ...
query2: ...
}
}]);
One such example of this is:
Link for Demo
angular.module('services', []).factory('factoryName', ["$filter",
function($filter) {
var method1Logic = function(args) {
//code
};
var method2Logic = function(args) {
//code
};
return {
method1: method1Logic,
method2: method1Logic
};
}
]).controller('MainController', ["$scope", "$rootScope", "$filter", "factoryName", function ($scope, $rootScope, $filter,factoryName) {
$scope.testMethod1 = function(arg){
$scope.val1 = factoryName.method1(arg);
};
$scope.testMethod2 = function(arg){
$scope.val2 = factoryName.method2(arg);
};
}]);
There is even a better version Opinionated version of this: References
function AnotherService () {
var AnotherService = {};
AnotherService.someValue = '';
AnotherService.someMethod = function () {
};
return AnotherService;
}
angular
.module('app')
.factory('AnotherService', AnotherService);
This is the service code:
myServices.factory('Auth', ['$resource',
function($resource){
return {
Login: $resource(serviceURL + 'login', {}, { go: { method:'POST', isArray: false }}),
Logout: $resource(serviceURL + 'logout', {}, { go: { method:'POST', isArray: false }}),
Register: $resource(serviceURL + 'register', {}, { go: { method:'POST', isArray: false }}),
};
}
]);
And from my controller I just have to add the go() function call to make it work:
Auth.Login.go({ username: $scope.username, password: $scope.password },
I guess I could have named the go function after the method and called it "post()" instead for clarity...
Yes, Of course, you can have multiple functions in an object. The only caveat is your service should return an object. You can have all the valid javascript members in that object as long as you follow object's syntax.
So following is possible
phonecatServices.factory('Phone', ['$resource',
function($resource){
return {
query: ... , // NOTICE THE COMMA HERE
query2: ...
}
}]);
You must be missing the comma (,) to separate your object's key values.

Resources