Unit test using jasmine for Service - javascript

Below is the convention followed in our project. Services will call resource files and returns promise.
This is my Service
angular.module('myModule').factory('myService', function(myResource) {
return {
exportToExcel: function(params) {
return myResource.exportToExcel($.param(params)).$promise;
},
getUsers: function(term) {
return myResource.getUsers({ term: term }).$promise;
}
}
});
And this is my Resource file
angular.module('myModule').factory('myResource', function($resource) {
return $resource('/report/', {}, {
exportToExcel: {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: 'arraybuffer',
url: '/abc/qwer',
transformResponse: function(data, headers) {
var response = {};
response.data = data;
response.headers = headers;
return response;
}
},
getUsers: {
method: 'GET',
url: '/abc/xyz',
isArray: true
}
})
});
I am finding it difficult to write unit test cases for these using jasmine. Could some one help with this as i am new to unit test cases.
I searched in google but could not find the examples suiting my need

This is typical example of how to test angular factories. You can have a look at the followings :
http://embed.plnkr.co/2i7IHs/
Testing an AngularJS factory with Karma (Jasmine)

Related

how to add specific interceptor to resource object get() or update() in AngularJS

I am currently using angular-hateoas (https://github.com/jmarquis/angular-hateoas). I would like to add specific interceptors to the query() and get() functions of the resource created in HateoasInterface. I have been looking for ways to do it, but not been successful.
I thought it could be done by adding it like this:
var someResource = someService.resource('someresource');
someResource.query.interceptors = {
response: function (data) {
// do something data
return data
},
responseError: function (error) {
// do something with error
return $q.reject(error);
}
};
but that gives me:
TypeError: Attempted to assign to readonly property.
I might need to use $decorator, but I have no experience with that, and I have seen no example for adding specific interceptors to specific resource objects.
I don't really want to use $httpProvider.interceptors, since I don't want the interceptor to work on all resources.
The only thing I can currently think of, is configuring HateoasInterfaceProvider with specificly named functions that contain the specific interceptors.
angular.module('myModule')
.config(HateoasInterfaceConfig);
HateoasInterfaceConfig.$inject = ['HateoasInterfaceProvider'];
function HateoasInterfaceConfig(HateoasInterfaceProvider) {
HateoasInterfaceProvider.setHttpMethods({
get: {
method: 'GET',
isArray: false
},
getSomeResource: {
method: 'GET',
isArray: false,
interceptors: {
response: someResponseFunc,
responseError: someErrorFunc
}
},
update: {
method: 'POST',
},
query: {
method: 'GET',
isArray: true
}
querySomeResource: {
method: 'GET',
isArray: true,
interceptors: {
response: function(data) {
// do something with data
return data;
},
responseError: function (error) {
//do something with error
return $q.reject(error);
}
}
});
HateoasInterfaceProvider.setLinksKey('_links');
}
but I prefer not to do it like that.
Figured it out.
When calling a resource, params and actions can be passed.
So like:
someServiceResult.resource('someresource',{},{get: {method: 'GET',...,
interceptor: { response: responseInterceptorFunc, ...}}})
Still not really the preferred solution, but when wrapped in a function in a service, acceptible.
I would like to have a solution that allows changing the interceptor definition for the Resource object created with:
someServiceResult.resource('someresource')
but I currently don't have time for figuring that out.

Parsing Error: Unexpected token

I am working on a MEAN STACK application and I am trying to create a AngularJS factory that makes use of $http. Below is the code of my gMapService.js.
gMapService.js
var myApp = myApp.factory("gMapService",['$http', function($http){
var urlBase = "https://mymapservice.com/api/function/json";
return {
function1: function (arg) {
return{
$http.get(urlBase, {
cache: true,
headers:{
"Content-Type":"application/json"
},
params:{
address:arg
}
})
.then(function (resp) {
return resp.data;
});
}
};
}]);
I have used a similar code in the past and I never had an issue with it until now where my code editor is signaling this error in
line 6: Parsing Error: Unexpected token .
Please tell me what i am doing wrong here. I am using angular 1.5.8
You have a misguided } character after the declaration of function1, just remove that character:
var myApp = myApp.factory("gMapService", ["$http", function($http) {
var urlBase = "https://mymapservice.com/api/function/json";
return {
function1: function(arg) {
return $http.get(urlBase, {
cache: true,
headers: {
"Content-Type": "application/json"
},
params: {
address: arg
}
})
.then(function(resp) {
return resp.data;
});
}
}
}]);

Angular $http's transformRequest doesn't change the headers

Good day!
I've created RequestTransformer service in order to change the content-type header and serialize post data.
Here is the method I use to change the headers and delegate data serialization to serializeData method (serializeData works fine).
class RequestTransformer implements IRequestTransformer {
public transformAsFormPost(data, getHeaders:IHttpHeadersGetter): string {
let headers = getHeaders();
headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
return RequestTransformer.serializeData(data) ;
}
/*Other code logic */
}
Also I've created test cases:
describe('Test RequestTransformerService functionality', function () {
let $httpBackend: IHttpBackendService;
let $http: IHttpService;
beforeEach(inject(function (_$httpBackend_, _$http_) {
$httpBackend = _$httpBackend_;
$http = _$http_;
}));
it('should transform post data as a regular form post', function () {
$http({
method: "POST",
url: 'test-transform.com',
transformRequest: RequestTransformer.transformAsFormPost,
data: {
id: 4,
name: "John",
status: "Best Friend"
}
});
$httpBackend.expectPOST('test-transform.com',
function (data) {
expect(data).toEqual('id=4&name=John&status=Best+Friend');
return data;
},
function (headers: Array) {
expect(headers['Content-Type']).toEqual('application/x-www-form-urlencoded; charset=utf-8');
return headers;
}).respond(201, '');
$httpBackend.flush();
})
});
The result of the test run is:
Expected 'application/json;charset=utf-8' to equal
'application/x-www-form-urlencoded; charset=utf-8'.
What could be the reason of that?

How to send a custom header on every request with an angular resource?

I like to send a custom header on every request with an angularjs resource. Before every request the header has to be created again. The following doesn't work. The header is calculated only once and because of this only one request works. A second request on the same resource fails. Its a lot of copy n paste of "headers: authhandler.createHeader()" also ...
myApp.service('Rest', ['$resource', 'authhandler',
function($resource, 'authhandler',{
return {
User: $resource( api_domain + "/api/users/:userid", {}, {
get: {method: 'GET', headers: authhandler.createHeader()},
remove: {method: 'DELETE', headers: authhandler.createHeader()},
edit: {method: 'PUT', headers: authhandler.createHeader()},
add: {method: 'POST', headers: authhandler.createHeader()},
patch: {method: 'PATCH', headers: authhandler.createHeader()}
}),
};
}]);
Has someone an idea how to solve this ?
I had a working solution but I don't like it because of huge amount of copy and paste source code:
myApp.controller('MyController', function(RestResource, authhandler, $routeParams) {
$http.defaults.headers.common = authhandler.createHeader();
RestResource.get({userid: $routeParams.id}, function(result) {
//...
});
});
I Would be very happy about hints how to solve this ! Thanks in advance!
You can use a request transformer:
function($resource, 'authhandler',{
return {
User: $resource( api_domain + "/api/users/:userid", {}, {
get: {
method: 'GET',
transformRequest: function(data, headersGetter) {
var currentHeaders = headersGetter();
angular.extend(currentHeaders, authhandler.createHeader());
return data;
}
},
You could also add the transformer to all requests:
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.transformRequest.push(function(data, headersGetter) {
var currentHeaders = headersGetter();
angular.extend(currentHeaders, authhandler.createHeader());
return data;
});
That way you don't have to configure anything or your resources.

AngularJS Resource with relation between tables

is this possible with AngularJS Resource?
/api/client/:id/jobs (get all the jobs from this client)
/api/client/:id/job/:jobId (get the job form this client)
My Factory:
.factory('Client', ['$resource', 'Api',
function ($resource, Api) {
var Client = $resource(Api.url() + 'client/:id/',
{
id: '#id'
},
{
'update' : { method: 'PUT', isArray: false }
}
);
return Client;
}
]);
Thanks!
I found a solution for my problem.
I have to create another factory to do the job:
.factory('ClientJobs', ['$resource', 'Api',
function ($resource, Api) {
var ClientJobs = $resource(Api.url() + 'client/:clientId/job/:jobId',
{
clientId: '#Id',
jobId: '#Id'
},
{
'query': { method: 'GET', isArray: true },
'update': { method: 'PUT' }
}
);
return ClientJobs;
}
]);
And, i can use the factory like this:
ClientJobs.save({clientId:clientId, jobId:job.id}, job, function (result) {
deferred.resolve(result);
}, function (reason) {
deferred.reject(reason);
});
Now, everything is working.
And for help those people who are working with UI-ROUTER, there is this question with an excellent answer about complex states like mine and nested views:
Nested Views with Nested States

Categories

Resources