How to write unit test to embeded ajax requests?

1.2k views Asked by At

I have the handleDownload method which starts a file download. The function posts to the backend, which gives back a response, based on that a new request posts to the server where the files are. I saw that I can use mockjax to mock the requests, but how to handle the different paths like success, error, etc. How should I know which response triggers which path (success,error, complete, ...). What would be a great startegy to test the handleDownload function, and how? For mocking I use Sinon.js I don't have a really deep understanding yet. I should also check either the handleDownloadFinal function is called.

handleDownload: function(data, url) {
$.ajax({
    type: "POST",
    url: url,
    data: {},
    success: function(response) {
        if (response.success) {
            var start_token = response.token;
            $.ajax({
                type: start_token.method,
                url: start_token.url,
                beforeSend: function(xhr) {
                    xhr.setRequestHeader('Authorization', start_token.header);
                },
                success: function(start_response) {
                    handleDownloadFinal(start_response.status_token);
                },
                error: function(start_response) {
                    $.ajax({
                        type: "POST",
                        url: url + 'proxy/',
                        success: function(fallback_response) {
                            if (fallback_response.success) {
                                handleDownloadFinal(fallback_response.status_token, true, fallback_response.job_uuid);
                            } else {
                                errorDownload(response.error);
                            }
                        },
                        error: function(fallback_response) {
                            // Now this is some real error                                    
                            generalErrorDownload();
                        },
                        dataType: 'json'
                    });
                },
                dataType: 'json',
                xhrFields: {
                    withCredentials: true
                }
            });
        } else {
            errorDownload(response.error);
        }
    },
    error: function(response) {
        generalErrorDownload();
    },
    complete: function() {
    },
    dataType: "json"
});

}
1

There are 1 answers

3
Andreas Köberle On BEST ANSWER

You should use the fake server coming with sinon.

before(function(){
    //create the server 
    this.server = sinon.fakeServer.create();
    // let the server automatically respond for every request
    server.autoRespond = true;
})

it('test something', function(){

    //let the server respond for  specific url with 200-ok
    this.server.respondWith("POST", "/some/article/comments.json", [200, {
      "Content-Type": "application/json"
    }, '[{ "id": 12, "comment": "Hey there" }]']);
})

As you have a bunch of requests and you have to check all combinations I would suggest to have helper function for every request fail success so you could test the cases like this:

function letFirstRequestSucceed() {
  this.server.respondWith("POST", "urlForFirstRequest", [200, {
    "Content-Type": "application/json"
  }, '[{ "id": 12, "comment": "Hey there" }]']);
}


function letSecondRequestFail() {
  this.server.respondWith("POST", "urlForSecondRequest", [404, {
    "Content-Type": "application/json"
  }, '{error: "some error message"}');
}


function letThirdRequestFail() {
  this.server.respondWith("POST", "urlForThirdRequest", [404, {
    "Content-Type": "application/json"
  }, '{error: "some error message"}');
}

it("should to something when the second and third request fails", function () {
  sinon.spy(window, 'generalErrorDownload');
  letFirstRequestSucceed();
  letSecondRequestFail();
  letThirdRequestFail();

  handleDownload('someDate', 'aUrl');

  expect(generalErrorDownload)

})

Btw you should think about to refactor you code using jquerys deferred which is supported by api ajax calls, this would make your could much more readable.