I want to test my controller, which makes an ajax call to my backend. Therefor I want to use jasmine and sinon. Ffor faking my backend server with sinon I tried something like this:
describe("fake server", function() {
var server;
beforeEach(function() {
this.server = sinon.fakeServer.create();
});
afterEach(function() {
this.server.restore();
});
it("calls callback with deserialized data", function () {
var callback = sinon.spy();
this.server.respondWith("GET", "/comments/1",
[200, {"Content-Type": "application/json"},
'{"comment":{"id":1,"title":"ducks and ducks"}}']);
commentController = App.CommentController.create();
//commentController.bind('getComment', callback);
commentController.getComment();
this.server.respond();
expect(callback.called).toBeTruthy();
expect(callback.getCall(0).args[0].attributes)
.toEqual({
id: "1",
title: "ducks and ducks"
});
});
});
My controller looks like this:
App.CommentController = Ember.Controller.extend({
getComment: function() {
$.ajax({
url: 'http://myapi/comments/' + id,
//...
error: function(jqXHR, textStatus){
this.set("error",true);
//do something
},
success: function(data) {
this.set("error",false);
//do something else
}
});
}
});
Can someone tell me how I get running this?
this.server.respondWith("GET", "http://myapi.com/comments/1",
[200, {"Content-Type": "application/json"},
'{"comment":{"id":1,"title":"ducks and ducks"}}']);
In my case the url should be absolute.
Related
Here I'm using Angularjs1.x and here is my condition. If condition is success then show the table otherwise throw an error. I know some code if its Success.
AngCtrl.Js
$scope.BtnCall = function () {
ServiceCntrl.CallData().then(function (d) {
$scope.EmpData = d.data;
});
}
AngService.Js
eApp.service("ServiceCntrl", function ($http) {
var xx = '';
xx= $http({
data: formData,
method: 'post',
url: Url,
datatype: "json"
}).success(function (rsp) {
RspData = rsp;
return RspData;
}).error(function (rsp) {
console.log('Error');
});
return xx;
};
Your x.then receives two functions x.then(function(){}, function(){}); first function is called when promise is successfully resolved and second function is called if promise is rejected(failed).
If your service function is return $http promise then your first function can have a parameter named(anything you like) and it will have response data that you can use. Second function can receive error parameters if any.
you should look at angular $http service documentation.
If your service is returning the promise of the get request, then you can write
$scope.BtnCall = function () {
var x = ServiceCntrl.CallData();
x.then(function(response) {
//Success callback
//code on success goes here
//response.data
}, function(response) {
//error callback
//code on error goes here
// server returns response with an error status.
});
you can use the ng-show/ng-hide to show and hide the contents on the html page.
You can write your success/fail code as the following:
$scope.BtnCall = function() {
var x = ServiceCntrl.CallData();
x.then(function(result) {
// Success code here
// Do something and resolved the promise
}, function(reason) {
// Error code here
// You may handle/reject the reason in params
});
});
See also the Angular docs for $q.
The AngularJS $http service makes a request to the server, and returns a response
The example above executes the $http service with an object as an argument. The object is specifying the HTTP method, the url, what to do on success, and what to do on failure.
$scope.BtnCall = function () {
ServiceCntrl.CallData().then(function (d) {
$scope.EmpData = d.data;
});
}
AngService.Js :
eApp.service("ServiceCntrl", function ($http) {
var xx = '';
xx= $http({
data: formData,
method: 'post',
url: Url,
datatype: "json"
}).success(function (rsp) {
RspData = rsp;
return RspData;
}).error(function (rsp) {
console.log('Error');
});
return xx;
};
I'm new to AngularJS and
I needed to know if we can make a jQuery like Ajax call in Angular and wanted to know it's complete syntax,
if anyone could help me making the whole code syntax.
Example in jQuery I could do something like -
$.ajax(
{
url: 'someURL',
type: 'POST',
async: false,
data:
{
something: something,
somethingelse: somethingelse
},
beforeSend: function()
{
$('#someID').addClass('spinner');
},
success: function(response)
{
$('#someID').removeClass('spinner');
console.log(response);
},
complete: function(response)
{
$('#someID').removeClass('spinner');
console.log(response);
},
error: function (errorResp)
{
console.log(errorResp);
}
});
Now here's what I found out on making http call in Angular,
Need help in building the complete syntax, with all possible options -
var req = {
method: 'POST',
url: 'someURL',
headers: {
'Content-Type': undefined
},
data: {
//goes in the Payload, if I'm not wrong
something: 'something'
},
params:{
//goes as Query Params
something: 'something',
somethingElse: 'somethingElse'
}
}
$http(req)
.then(function()
{
//success function
},
function()
{
//Error function
});
now what if I want to attach a spinner on some id in the BeforeSend function like in jQuery and remove the spinner in success,
What is the Angular's way as a like to like for BeforeSend or making the http call async?
Angular even let you control this better :). Two ways can be chosen here:
1. Wrapping $http
You can write for each request with by using a wrapper of $http which will add some methods before and after you made request
app.factory('httpService',function($http){
function beginRequest() {};
function afterRequest() {};
return {
makeRequest: function(requestConfig){
beginRequest();
return $http(requestConfig).then(function(result){
afterRequest(result);
});
}
}
})
Then each time you can call this function to make a request. This is not new.
2. Using interceptor
Angular has a better way to handle for all request. It use a new concept named 'interceptor'. You write your interceptor as a normal service and push one or many interceptors into $http service and depend on type of interceptor, it will be called each time your request happen. Look at this picture to think about interceptor:
Some common task for interceptor can be: Add/remove a loading icon, add some more decorator to your http config such as token key, validate request, validate responded data, recover some request...
Here is example of a interceptor that add a token key into headers of a request
app.service('APIInterceptor', function($rootScope, UserService) {
var service = this;
service.request = function(config) {
var currentUser = UserService.getCurrentUser(),
access_token = currentUser ? currentUser.access_token : null;
if (access_token) {
config.headers.authorization = access_token;
}
return config;
};
service.responseError = function(response) {
return response;
};
})
Then add interceptor to your $http:
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('APIInterceptor');
}]);
Now all request will be added a token key to header. cool right?
See here for more information:
there is eveyrthing here to help with your question :https://docs.angularjs.org/api/ng/service/$q http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/
$http functions are async by default.
And regarding the beforesend function, you could wrap the http call in a function and add the spinner just before making the call and remove it in the success call back. Something like this,
var makeHttpRequest = function(){
$('#someID').addClass('spinner');
$http(req).then(function(){
$('#someID').removeClass('spinner');
//rest processing for success callback
},function(){
$('#someID').removeClass('spinner');
//Error callback
});
}
The way I have implemented complex get and post in my angular application is as below:
Create a CRUDService as below:
yourApp.service('CRUDService', function ($q, $http) {
this.post = function (value, uri) {
var request = $http({
method: "post",
url: uri,
data: value
});
return request;
}
this.get = function (uri) {
var request = $http({
method: "get",
url: uri
});
return request;
}
});
As you can see this service simply returns a get/post object. Somewhere in my controller I use this service as below:
$('#exampleButton').button("loading"); //set the element in loading/spinning state here
var getObj = CRUDService.get("/api/get/something");
getObj.then(function(data){
//do something
$('#exampleButton').button("reset"); //reset element here
}, function(err){
//handle error
$('#exampleButton').button("loading"); //reset element here
});
$('#exampleButton').button("loading"); //set the element in loading/spinning state here
var postObj = CRUDService.post(postData,"/api/get/something");
postObj.then(function(data){
//do something
$('#exampleButton').button("reset"); //reset element here
}, function(err){
//handle error
$('#exampleButton').button("loading"); //reset element here
});
I hope this helps :)
The http call is async - it returns a promise that you can then handle with the try() and catch() methods. You can simply wrap your calls i.e.
function makeRequest() {
$scope.showSpinner = true;
$http
.get('http://www.example.com')
.then(function (response) {
$scope.showSpinner = false;
})
.catch(function (err) {
$scope.showSpinner = false;
});
}
If you would however like you use familiar syntax akin to jQuery then you can push your own custom interceptors. This will allow you intercept the requests and response and do whatever you want. In the below example we call functions if they are defined.
angular
.module('app', [])
.config(appConfig)
.factory('HttpInterceptors', httpInterceptors)
.controller('MyController', myController);
// app config
appConfig.$inject = ['$httpProvider'];
function appConfig($httpProvider) {
// add out interceptors to the http provider
$httpProvider.interceptors.push('HttpInterceptors');
}
// http interceptor definition
function httpInterceptors() {
return {
request: function(request) {
if (angular.isFunction(request.beforeSend)) {
request.beforeSend();
}
return request;
},
response: function(response) {
if (angular.isFunction(response.config.onComplete)) {
response.config.onComplete();
}
return response;
}
}
}
// controlller
myController.$inject = ['$scope', '$http', '$timeout'];
function myController($scope, $http, $timeout) {
$scope.showSpinner = false;
$http({
method: 'GET',
url: 'https://raw.githubusercontent.com/dart-lang/test/master/LICENSE',
beforeSend: function() {
$scope.showSpinner = true;
},
onComplete: function() {
$timeout(function() {
console.log('done');
$scope.showSpinner = false;
}, 1000);
}})
.then(function(response) {
console.log('success');
})
.catch(function(err) {
console.error('fail');
});
}
.spinner {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<div ng-app='app' ng-controller='MyController'>
<div ng-class='{spinner: showSpinner}'>
Hello World!
</div>
</div>
Here is my code:
function sendRequestData(url, urlParameters) {
$.ajax({
url : url,
method : 'POST',
headers : {
'Accept' : 'application/json'
},
contentType : 'application/json',
data : JSON.stringify(urlParameters),
dataType : "json",
success : function(data) {
successCallBack(data)
},
error : function(data, status, errorThrown) {
failCallBack(data, status, errorThrown)
}
});
I want to mock and test this ajax call. Is there anyway I can do that?
If your test are hard to test, this means you are doing something wrong.
In your specific case, you need follow Dependency Inversion principle (think Dependency Injection) and inject your requirements into your function. Basically, you need to pass in all the dependencies including $, successCallback and failCallback. This would let you mock your ajax calls with Jasmine's spyOn() method and then check for correct function calls.
function sendRequestData(url, urlParameters, $, successCallBack, failCallBack) {
$.ajax({
url : url,
method : 'POST',
headers : {
'Accept' : 'application/json'
},
contentType : 'application/json',
data : JSON.stringify(urlParameters),
dataType : "json",
success : function(data) {
successCallBack(data)
},
error : function(data, status, errorThrown) {
failCallBack(data, status, errorThrown)
}
});
}
Your tests might look like this. I have not checked it, but you get an idea of what I mean.
describe("sendRequestData() does correct ajax calls", function() {
var $ok, $error, successCallback, failCallback = null;
beforeEach(function() {
// You can create a spy object using this syntax
$ok = jasmine.createSpyObj('$', ['ajax']);
// Or define it yourself like so
$ok = {
ajax: function(value) {
successCallback();
}
};
$error = {
ajax: function(value) {
failCallback();
}
};
spyOn($, 'ajax');
spyOn(successCallback);
spyOn(failCallback);
});
it("calls successCallback on success", function() {
sendRequestData('url', {}, $ok, successCallback, failCallback);
expect($.ajax).toHaveBeenCalled();
expect(successCallback).toHaveBeenCalled();
expect(failCallbackCallback).not.toHaveBeenCalled();
});
it("calls failCallback on failure", function() {
sendRequestData('url', {}, $error, successCallback, failCallback);
expect($.ajax).toHaveBeenCalled();
expect(successCallback).not.toHaveBeenCalled();
expect(failCallbackCallback).toHaveBeenCalled();
});
});
Or simply use jasmine-ajax plugin to mock your ajax calls.
If you are doing this on legacy code and cannot change the JS code maybe you can try as below
JS file
$.ajax({
async : true,
type : "POST",
data : requestPayload,
url : APIURL,
contentType: "application/json",
success : function (response) {
/* -- some code here --*/
},
error : function (errorResponse) {
/* -- some code here --*/
}
});
SPEC file
it("check api call", function () {
var testResponse = {
'status' : 'ok',
'errorCode' : '',
'message' : 'this is a mock response'
};
/*...*/
spyOn($, 'ajax').and.callFake(function(e) {
return e.success(testResponse);
// for failure case
//return e.error({
// 'status' : 'not_ok',
// 'errorCode' : 'Unauthorized'
//});
});
form.submit();
});
You can also call the e.success and
return $.Deferred().resolve(testData).promise(); from what I have understood in other examples.
Mocking jQuery ajax calls with Jasmine
spyOn($, 'ajax').and.callFake(function (e) {
e.success(testData)
return $.Deferred().resolve(testData).promise();
});
I am using Jasmine and Sinon to test an ajax call. The test looks like this:
describe("function initialize", function(){
var server;
beforeEach(function(){
server = sinon.fakeServer.create();
});
afterEach(function() {
server.restore();
});
it ("should make an ajax call successfully", function(){
server.respondWith(session.apipath + "/login/refreshToken/",
[200, { 'Content-Type': 'application/json' },
'{user:"asdf",loginToken:"bla"}']);
session.initialize();
server.respond();
expect(localStorage.getItem("loginToken")).toBe("bla");
});
});
I want it to call the success function.
$.ajax(this.apipath + "/login/refreshToken/", {
success: function (response) {
alert("success!!!");
localStorage.setItem("loginToken", response.loginToken);
},
error: function(){
alert("error!!!");
}
});
But only error is called. What am I doing wrong?
You can try this. (Although this is late, I still want to suggest you.)
'{user:"asdf",loginToken:"bla"}' -> '{"user":"asdf", "loginToken":"bla"}'
If you want to know why, read this.
I have a dojo class like this.
var widget = declare("app.util",null, {
createSecuredLayers: function () {
$.ajax.get({
url: "/Api/GetLayer",
success: function (e) {
},
error: function () {
}
});
}
});
I want to use this object with callback parameters. I mean I want to pass success and error callbacks as parameter.
var util = new app.util();
util.createSecuredLayers({
success:function(){ },
error:function(){ }
});
createSecuredLayers: function(item) {
$.ajax.get({
url: "/Api/GetLayer",
success: item.successCallback,
error: item.errorCallback
});
}
When you call the method, don't forget to pass the response in the success callback.
util.createSecuredLayers({
successCallback: function(resp) {},
errorCallback: function(err) {}
});
You can do it like this:
var widget = declare("app.util",null, {
createSecuredLayers: function (args) {
$.ajax.get({
url: "/Api/GetLayer",
success: args.success,
error: args.error
});
}
});
var util = new app.util();
util.createSecuredLayers({
success:function(){ },
error:function(){ }
});
You should also consider using Dojo's deferred