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.
Related
I am trying to call show function inside Axios request, My Axios request inside another function as shown below:
My Axios request inside Myfunction:
axios({
method: "Get",
timeout: 3000,
headers: {
..................
},
url: "https://XXXXXX/"
})
.then( function(response) {
console.log(response);
//Call function
app.show.bind(response);
})
.catch(function(error) {
console.log(error);
});
And function show is in the method section:
show (workspace_info) {
alert("I am here");
},
but I got an error message:
TypeError: Cannot read property 'bind' of undefined
A very simple method would be to do this:
app.show = function( workspaceInfo ) { // notice the camel case ;)
alert( 'I am here!' );
}
And then bind it to the app like so:
app.show = app.show.bind( this ); // this is something we do a lot in React
Finally, you can use it like:
app.show( response );
Now, remember that you do all the setting up before you actually call the function.
I'm having some trouble handling multiple jquery ajax call, there are timeout error, but how do I know which request error this is?
$.when(ajaxDeferred1, ajaxDeferred2)
.done(function(result1, result2) {})
.fail(function(response, statusText) {
// how do I know which(ajaxDeferred1 or ajaxDeferred2) ajax call error this is?
});
ajaxDeferred1
$.ajax({
method: 'GET',
url: xxx,
timeout: 5000,
});
I know I can handle error by putting '.fail()' on each request, but is there any way handle error above way?
Going further, can I handle like this?
$.when(ajaxDeferred1, ajaxDeferred2)
.done(function(result1, result2) {})
.fail(function(errorForRequest1, errorForRequest2) {
// handle error
});
EDIT:
I think I need to make my question more clear. In the above example:
$.when(ajaxDeferred1, ajaxDeferred2)
.done(function(result1, result2) {})
.fail(function(errorForRequest1, errorForRequest2) {
// if all request has done, but one or more request has got error, return the error here then!
// So I can handle which part UI should show and which UI part I should hide due to the error!
});
I want to get 'done' result when all is done without error, and get 'error' when all is done but one or more request has encountered problem and return them all together into '.fail()'.
You can use .always() and within it iterate over each promise and check whether it resolved or failed.
var promises = [ajaxDeferred1, ajaxDeferred2]
$.when.apply($, promises)
.always(function() {
$.each(promises, function(i) {
this.done(function(result) {
console.log('promise', i, 'resolved');
}).fail(function(error) {
console.log('promise', i, 'failed');
});
});
});
JSFiddle demo: https://jsfiddle.net/pr45eov1/3/
I like #Miguel Mota's answer. But as an alternative, you are going to get your deferred object back if it fails. So you can add some data to it:
var dfd1 = jQuery.ajax({
method: 'GET',
url: 'some request that fails first',
timeout: 1
});
dfd1.id = 1;
var dfd2 = jQuery.ajax({
method: 'GET',
url: 'some request that fails second',
timeout: 1000
});
dfd2.id = 2;
jQuery.when(dfd1, dfd2)
.done(function () { })
.fail(function (request) {
// id: 1
console.log('id: ' + request.id);
});
I'm using https://github.com/danialfarid/angular-file-upload for my file uploads. It provides a progress method that is called, when the xhr requests receives the progress event. This is from the source code of angular-file-upload:
xhr.upload.addEventListener('progress', function(e) {
deferred.notify(e);
}, false);
My problem is now, how should I test this using $httpBackend? I can test the success and error methods with
$httpBackend.expectPOST("http://localhost:9001/").respond('ok');
$httpBackend.expectPOST("http://localhost:9001/").respond(500, 'some error');
but I can't get the notify of the promise to fire. Is there a way to do this?
EDIT
The part that I want to test, is inside the progress method:
$upload.http({url: url, method: 'POST', data: file})
.progress(function(evt) {
// here is more code, that needs to be tested
self.$deferreds.upload.notify((100.0 * evt.loaded / evt.total).toFixed(2));
}).success(function(data, status, headers, config) {
self.$deferreds.upload.resolve(data);
}).error(function(response) {
self.$deferreds.upload.reject(response);
});
You want to spy on the $upload.http method and return a mocked object that lets you register progress, success and error callbacks.
spyOn($upload, 'http').andReturn({
progress: function (progressCallback) {
this.progressCallback = progressCallback;
},
success: function (errorCallback) {
this.errorCallback = errorCallback;
},
error: function (errorCallback) {
this.errorCallback = errorCallback;
}
});
Then you can call these callbacks synchronously in the tests:
it('should do something', function () {
$upload.progressCallback();
// or $upload.successCallback();
// or $upload.errorCallback();
expect('this').toBe('that');
});
We are speaking about unit-tests?
Why do you need to test 3rd-party at all?
Just mock this all part.
Probably I did not get the idea of the question, so need more code that should be covered by tests.
I am using Laravel 4.2.6
This is my function with an ajax call to the controller's method called savesession
function saveActualSession() {
return $.ajax({
url: 'savesession',
data: {
my_username: $('input#username').val()
},
type: 'POST',
dataType: 'json',
success: function(response) {
console.log("success");
}
});
}
In controller I have this:
public function savesession()
{
if(Request::ajax())
{
$my_username = Input::post('my_username');
if ($my_username) { Session::put('my_username', $my_username); }
return $my_username;
}
}
Sessions saving is triggered like this on different places in my javascript code:
saveActualSession()
.done(function(e) {
// Things to be done after saving session
})
.fail(function(e) {
alert('oh no!')
});
The problem is that it's giving me this error in the console:
"NetworkError: 500 Internal Server Error - http://laravelsite.dev/savesession"
It's weird because the url exists 100%, because when I try to do this in the controller:
public function savesession()
{
if(Request::ajax())
{
$my_username = Input::post('my_username');
if ($my_username) { Session::put('my_username', $my_username); }
return $my_username;
}
else
{
print_r("url is working");
die();
}
}
and I access the url directly in my browser like:
http://laravelsite.dev/savesession
It's giving me the print_r message url is not working and it dies.
btw. my routes look like this:
Route::any('savesession', ['as' => 'savesession','uses' => 'RegistrationController#savesession']);
What am I doing wrong?
I have a similar AJAX function for getting sessions and that route works fine and no server errors are shown.
Any idea?
You have a wrong method there. Simply change...
$my_username = Input::post('my_username');
to this...
$my_username = Input::get('my_username');
Get does not refer to the HTTP Method in this context, it refers to what Laravel is doing - get an input value. This value can be GET or POST, it doesn't actually make a difference.
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.