atecarlos / protractor-http-mock

A library designed to work alongside Protractor for setting up mocks for your HTTP ajax requests.
MIT License
173 stars 70 forks source link

Interceptors + protractor-http-mock results in no $http call being completed #91

Closed shssoichiro closed 8 years ago

shssoichiro commented 8 years ago

I have a responseError interceptor, and most of my tests (that don't go through any interceptors) work without issues, but my test that should return a mocked response error fails--it doesn't show any error message out of the ordinary, just the standard "No element found using locator" as if the test was failing. As far as I can tell, it's behaving as if no API call (mocked or real) is being made.

The interceptor code:

$httpProvider.interceptors.push(($rootScope, $q) => {
  'ngInject';
  return {
    responseError: response => {
      if (response.status >= 400) {
        if (response.data.message) {
          $rootScope.message = response.data.message;
        } else if (response.data.errors) {
          const firstError = _head(_head(_values(response.data.errors)));
          $rootScope.message = {
            type: 'danger',
            text: firstError,
          };
        }
      }

      return $q.reject(response);
    },
  };
});

The test (also attempted having protractor manually wait for #global-msg-text, which resulted in a timeout):

it('should show validation messages', function () {
  element(by.id('student-name-new')).clear();
  element(by.id('student-save-new')).click();
  expect(element(by.id('student-id-1')).getText()).toEqual('1');
  expect(element(by.id('student-id-2')).getText()).toEqual('2');
  expect(element(by.id('student-id-3')).getText()).toEqual('3');
  expect(element.all(by.id('student-id-4')).count()).toEqual(0);
  expect(element(by.id('student-name-1')).getText()).toEqual('Student 1');
  expect(element(by.id('student-name-2')).getText()).toEqual('Student 2');
  expect(element(by.id('student-name-3')).getText()).toEqual('Student 3');
  expect(element(by.id('global-msg-text')).getText()).toEqual('The name field is required.');
});

The mock:

{
  request: {
    path: '/students',
    method: 'POST',
    data: {
      name: '',
    },
  },
  response: {
    data: {
      errors: {
        name: [
          'The name field is required.',
        ],
      },
    },
    status: 422,
  },
},
cezarpavelski commented 8 years ago

My application works perfectly without the mock, but when I use mock happens this error.

My Interceptor:

(function(){
  'use strict';

    angular.module('XXXX')
      .factory('AuthTokenInterceptor', AuthTokenInterceptor);

         function AuthTokenInterceptor($q, $injector){
           return {
             'request': function(config) {
                if (sessionStorage.getItem('access_token')) {
                  config.headers['Authorization'] = sessionStorage.getItem('token_type')+ ' '+sessionStorage.getItem('access_token');
                }
                return config;
              }
          }
       }
       AuthTokenInterceptor.$inject = ['$q', '$injector'];
})();

angular.module('XXXX').config(['$httpProvider', function($httpProvider) {
  $httpProvider.interceptors.push('AuthTokenInterceptor');
}]);

The mock:

{  
       request: {
            path: 'http://app.com/verifyUnique/name/John/',
            method: 'GET',
            headers: { authorization: 'Bearer i2npWMAocSEtmktmebMYFcBtctEY7TEhqMLldZh5' }
        },
        response: {
            data: {
                "error": false,
                "message": "Name is available"
            }
        }   
}

The Error: Failed: unknown error: Cannot set property 'Authorization' of undefined

atecarlos commented 8 years ago

Hi @shssoichiro . The plugin as of now does not support responseError and requestError interceptors. This a new feature that we need to add. I'll get to it as soon as I can, or hopefully someone can take it on and submit a PR.

eddie commented 8 years ago

@cezarpavelski It's not ideal, but have you considered (in this situation) setting the access token with $http defaults instead?

For example (from the angular docs)

$http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w';
slonya4ka commented 8 years ago

@cezarpavelski i have the similar issue with headers. When I use protractor-http-mock my application faills here in http.js because request.headers == undefined:

request: function (request) {
            **if (request.method === 'POST' && request.headers['Content-Type'].indexOf('application/json') > -1) {**
                var now = new Date();
                // copy to prevent original data damage
                request.data = angular.copy(request.data);
                correctDates(request.data);
                log.debug('Request preprocessing JSON took ' + (new Date() - now) + ' ms');
            }

            return request;
        }

However, if I don't use this library than request.headers == {} with necessary properties.

atecarlos commented 8 years ago

@cezarpavelski @slonya4ka I just pushed a new version 0.8.0 that adds empty default headers if none are provided. I think this may solve your issue. Please let me know how it goes.

shssoichiro commented 8 years ago

I finally have a chance to work on this. I've produced a failing test case and hope to be able to PR a fix within the next couple of days.