AngularJS - Unit testing file uploads

Egor Smirnov

As you know, inside unit tests it's built-in angularjs feature to mock XHR requests with $httpBackend - this is nice and helpful while writing unit tests.

Recently, I met with need of mocking XHR in case of file upload and discovered some problems.

Consider following code:

var xhr = new XMLHttpRequest();

xhr.upload.addEventListener("progress", uploadProgress(event), false);
xhr.addEventListener("load", uploadComplete(event), false);
xhr.addEventListener("error", uploadError(event), false);
xhr.addEventListener("abort", uploadAbort(event), false);
xhr.open("POST", 'some url');
xhr.send(someData);

What I want to do is to do unit testing of such a code with mocking of XHR requests, but it's not possible do it because there is no $http service used here.

I tried this (and it's working and could be mocked with $httpBackend):

$http({
    method: 'POST', 
    url: 'some url', 
    data: someData, 
    headers: {'Content-Type': undefined},
    transformRequest: angular.identity})
.then(successCallback, errorCallback);

But in this case I don't know how to implement 'progress' callback and 'abort' callback (they are essential and required in case I am working on now).

I've seen information that latest Angular supports progress callback for promises (not sure though whether it's integrated with $http service), but what about abort callback?

Any ideas or maybe your met with something similar before?

dnc253

If the $http service doesn't give you everything you need, you can still unit test the first block of code. First of all, change your code to use Angular's $window service. This is just a wrapper service, but it allows you to mock the object in your tests. So, you'll want to do this:

var xhr = new $window.XMLHttpRequest();

Then in your tests, just mock it and use spies.

$window.XMLHttpRequest= angular.noop;
addEventListenerSpy = jasmine.createSpy("addEventListener");
openSpy = jasmine.createSpy("open");
sendSpy = jasmine.createSpy("send");
xhrObj = {
   upload: 
   {
       addEventListener: addEventListenerSpy
   },
   addEventListener: addEventListenerSpy,
   open: openSpy,
   send: sendSpy
};
spyOn($window, "XMLHttpRequest").andReturn(xhrObj);

From there, you can make the different spies return whatever you want for the different tests.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related