Rory
Rory

Reputation: 1492

Jasmine, Unit testing XMLHttpRequest with Promises

I have the following function, that uses the Q promise library

getConfig: function(params){

            return this.codeApiClient.get(this.endpoints.config, params, {}).then(function(response){
                return response;
            }, function(err){
                throw err;
            });
        }

The above code calls the API code shown below (I've abbreviated the code to rid noise)

CodeApiClient.prototype = {
  get: function(endpoint, paramStr, headers){
      var defer = new Q.defer();
      var start_time = new Date().getTime();

      var req = new XMLHttpRequest();
      var url = endpoint + (paramStr.indexOf('?') !== -1 ? paramStr : '?' + paramStr);

      req.open('GET', url);

      req.onload = function() {
          var request_time = new Date().getTime() - start_time;
          // This is called even on 404 etc
          if (req.status < 400) {
              var response = JSON.parse(req.response)
              response.__request_time = request_time;
              defer.resolve(response);
          } else {
              // Otherwise reject with the status text
              defer.reject(Error(req.statusText));
          }
      };
}

My question is: How do I write a Jasmine test for getConfig i.e. faking the response and stubbing the underlying XMLHttpRequest ? Is sinon.js capable of this. I know it can stub callbacks on $.ajax, but I'm not sure how to do this with a promise lib such as Q. Note this is pure JavaScript, no angular etc

Upvotes: 1

Views: 843

Answers (2)

Winter Soldier
Winter Soldier

Reputation: 2685

  • Here is how to use callFake in jasmine to return a promise.
  • Now since both Q as well as traditional jQuery provide the deferred objects, you could substitute $.Deferred() with Q.defer();

var tempObj = {
    	getConfig: function(params){

                return this.codeApiClient.get(this.endpoints.config, params, {}).then(function(response){
                    return response;
                }, function(err){
                    throw err;
                });
            }
        codeApiClient : {
          get : function(){
            // some get function of codeApiClient
          }
        }
    }


    it('test getConfig success', function(){
    	var dummyResponse = {'someDummyKey' : 'someDummyValue'};
    	spyOn(tempObj.codeApiClient, 'get').and.callFake(function(e){
    		return $.Deferred().resolve(dummyResponse).promise();
    	}); 
      tempObj.getConfig({});
      //any expectations
    });

    it('test getConfig failure', function(){
    	var dummyResponse = {'error' : 'someDummyFailure'};
    	spyOn(tempObj.codeApiClient, 'get').and.callFake(function(e){
    		return $.Deferred().reject(dummyResponse).promise();
    	});
       tempObj.getConfig({});
      //any expectations
    });

Upvotes: 1

Rory
Rory

Reputation: 1492

If anyone is interested here's my Jasmine test, hope it helps

define([ 'q', 'lodash', 'jquery',  'ChatApi'], function (Q, _ , $ ,  ChatApi) {

    describe('Chat Api test', function () {
        var categories
        var chatApi;
        var fakeResponse;

        beforeEach(function() {
            //fakes
             categories = {
                "l10n": {
                    "defaultLanguage": "en-GB",
                    "languages": [
                        {
                            "name": "en-GB",
                            "value": "Tell me more..."
                        },
                        {
                            "name": "fr",
                            "value": "On veut tout savoir..."
                        },
                        {
                            "name": "de",
                            "value": "Wähle die passende Kategorie aus..."
                        }
                    ]
                }
            };
            fakeResponse = {
                'categories': categories
            }
            chatApi = new ChatApi("https://server/gateway/","v1");
        });

        it('test getConfig success', function(done){
            var getConfigCalled = spyOn(chatApi, 'getConfig').and.callFake(function(e){
                //jQuery version of promises
               //return $.Deferred().resolve(fakeResponse).promise();
                var deferred = Q.defer();
                deferred.resolve(fakeResponse);
                return deferred.promise;
            });

            chatApi.getConfig({}).then(function(response){
                //compare objects using lodash
                var x = _.isEqual(response.categories, fakeResponse.categories);
                expect(x).toBe(true);
            })

            expect(getConfigCalled).toHaveBeenCalled();

            done();
        });

    });
});

Upvotes: 0

Related Questions