Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

expectHEAD is documented but not implemented?

In our internal angularjs project, one of the services has $http.head() call which I'm trying to test.

For testing, I'm using Fake HTTP backend provided by angular-mocks. Here is the relevant code:

it('handle status code 200', inject(function ($httpBackend, ConnectionService) {
    spyOn(Math, 'random').andReturn(0.1234);

    httpBackend = $httpBackend;
    httpBackend.expectHEAD('ping?rand=1234').respond(200);
    ConnectionService.sendRequest();
    httpBackend.flush();

    expect(ConnectionService.stats.packetsReceived).toEqual(5);

    httpBackend.verifyNoOutstandingExpectation();
    httpBackend.verifyNoOutstandingRequest();
}));

Running the test results into the following error:

PhantomJS 1.9.7 (Mac OS X) connection service tests sendRequest function handle status code 200 
FAILED  TypeError: 'undefined' is not a function (evaluating 'httpBackend.expectHEAD('ping?rand=1234')')
at /path/to/app/app-connection-service_test.js:66
at d (/path/to/app/bower_components/angular/angular.min.js:35)
at workFn (/path/to/app/bower_components/angular-mocks/angular-mocks.js:2159)

After digging a little bit, I've found the relevant github issue:

  • fix($httpBackend): Add missing expectHEAD() and expectOPTIONS() methods

which, as far as I understand, means that there really is not expectHEAD() method in angular-mocks - it is documented, but, in reality, it is not yet a part of a stable angular release.

What is the best way to proceed?

Note that I have to stay with angular <= 1.2, since this app needs to run on IE8 (Angular 1.3 is dropping support for IE8).


One of the workarounds I'm thinking about currently is to replace head() with get(). In this case, I can test it with existing expectGET() method. But I'm not sure about the drawbacks.

like image 234
alecxe Avatar asked Sep 19 '14 17:09

alecxe


2 Answers

You could just add in the change yourself: https://github.com/revolunet/angular.js/commit/b2955dd52725241dd9519baa12fe8ca74659004b

It's a one line change in angular-mocks.js on line 1523:

1523: -    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {
1523: +    angular.forEach(['GET', 'DELETE', 'JSONP', 'HEAD'], function(method) {    

Seeing as you have to stay with a non-current version of Angular anyways, it shouldn't cause too many issues in the future.

Edit: reviewing JoelJeske's answer, he makes a good point - you could easily do this without forking. The one change I would make to his solution, is instead of calling the method directly

$httpBackend.expect('HEAD', 'ping?rand=1234').respond(200);

I would instead create the shortcut method directly:

$httpBackend.expectHEAD = function(url, headers) {
    return $httpBackend.expect('HEAD', url, undefined, headers);
};

And then you can do:

$httpBackend.expectHEAD('ping?rand=1234').respond(200);
like image 122
dave Avatar answered Oct 04 '22 22:10

dave


As opposed to forking and editing a library, it would be much better practice to use the underlying method.

$httpBackend.expect('HEAD', 'ping?rand=1234').respond(200);

The other method you cannot use is just a shortcut method. It is much better and easier to use this method than changing the library.

like image 44
Joel Jeske Avatar answered Oct 04 '22 23:10

Joel Jeske