5

I have a web app that needs to check if the user is connected to the internet. In the implementation, the check() function promises to true if an ajax ping to a known endpoint succeeds and false if the ajax call fails in any way.

In Jasmine, I can use request.respondWith({status:400, etc}) to simulate a failure, but I can't work out how to simulate the more fundamental error of the call not being made at all.

In practice, browsers seem to 'return' a status code 0 and readyState 4 when the call could not even be made.

How should I approach this in my Jasmine tests?

Robin
  • 698
  • 6
  • 25

1 Answers1

0

This is an interesting question. Though I might not provide you a straight forward answer for it, I'd like to take a stab at it.

The code below illustrates three such examples (tests rather). See it in action

  var errorFunction = function(jqXHR, status, error) {  
    console.log('This is errorFunction')  
  }

  var makeAPICall = function(url) {
    return $.ajax({
      url: url,
      fail: errorFunction,
      error: errorFunction
    });
  }

  var testFunction = function() {
    makeAPICall().done(function(data, status, xh) {
      if (xh.status === 0 && xh.readyState == 4) {
        errorFunction();
        return;
      }
      console.log("this is successFunction");
    }).fail(errorFunction);
  }

  var getData = function() {
    var str = 'ABCDEFGHIJ'
    var returnStr = '';
    for (var i = 0; i < 3000; i++) {
      returnStr += str;
    }
    return returnStr;
  }

  describe('test ajax errors', function() {
    it('tests a failed call due to huge payload ', function() {
      var xhrObj = $.ajax({
        url: 'https://jsonplaceholder.typicode.com/posts?userId=' + getData(),
        async: false
      });
      console.log('Below is the xhr object that is breing returned via spy');
      console.log(xhrObj);    
      spyOn(window, 'makeAPICall').and.returnValue(xhrObj);
      spyOn(window, 'errorFunction').and.callThrough();    
      testFunction();
      expect(window.errorFunction).toHaveBeenCalled();
    });

    it('tests a failed call due to some n/w error scenario (readyState->4, status->0)', function() {
      var xhrObj = $.ajax({
        url: '',      
        async: false
      });
      xhrObj.status = 0;
      xhrObj.statusText = 'error';
      console.log('Below is the xhr object that is breing returned via spy');
      console.log(xhrObj);    
      spyOn(window, 'makeAPICall').and.returnValue(xhrObj);
      spyOn(window, 'errorFunction').and.callThrough();    
      testFunction();
      expect(window.errorFunction).toHaveBeenCalled();
    });

    it('tests a failed call (bad url pattern)', function() {
      var xhrObj = $.ajax({
        url: 'https://jsonplaceholder.typicode.com/postssss/1',
        async: false
      });
      console.log('Below is the xhr object that is breing returned via spy');
      console.log(xhrObj);    
      spyOn(window, 'makeAPICall').and.returnValue(xhrObj);
      spyOn(window, 'errorFunction').and.callThrough();    
      testFunction();
      expect(window.errorFunction).toHaveBeenCalled();
    });


  });

Notes:

  • errorFunction is the errorFunction that gets called from the done if the readySatate === 4 && status === 0 and also all other error/fail callbacks
  • makeAPICall returns the jqXHR on which done & fail callbacks are used.
  • getData is a utility function which generates a huge payload: used in test1
  • second test is about making a dummy ajax call with empty url so as to simulate readyState->4 & status->0
  • the third test simulates the usual bad request url pattern test.
  • for all the 3 scenarios, I've used a jqXHR object that I created by $.ajax({some params & async false})
  • setting async: false helps me to generate a dummy object and pass it over to the function via a spy
Winter Soldier
  • 2,607
  • 3
  • 14
  • 18