Подтвердить что ты не робот

Angular Перехватчик ответных реакций на жасмин

Я пытаюсь проверить свой ответный перехватчик, но мне трудно понять, как издеваться над объектом $window. Вот мой код перехватчика:

'use strict';

angular.module('Domain.handlers')

.config(function($httpProvider) {
  $httpProvider.responseInterceptors.push('UnauthorizedInterceptor');
})

.factory('UnauthorizedInterceptor', function($q, $injector, $window, ENV) {
  return function(promise) {
    var success = function(response) { return response; };
    var error   = function(response) {
      if (response.status === 401) {
        $window.location.href = ENV.account + '/oauth/authorize?client_id=' + ENV.clientId + '&redirect_uri=' + ENV.app + '/oauth/callback&response_type=token';
      }
      return $q.reject(response);
    };
    return promise.then(success, error);
  };
});

И вот моя спецификация:

'use strict';

describe('Domain.handlers.response', function() {
  var UnauthorizedInterceptor,
      httpProvider,
      $httpBackend,
      $http,
      token = '123456789';

  beforeEach(module('Domain.handlers', function($httpProvider) {
    httpProvider = $httpProvider;
  }));

  beforeEach(inject(function(_UnauthorizedInterceptor_, _$httpBackend_, _$http_) {
    UnauthorizedInterceptor = _UnauthorizedInterceptor_;
    $httpBackend = _$httpBackend_;
    $http = _$http_;
  }));

  describe('UnauthorizedInterceptor', function() {
    it('should be defined', function() {
      expect(UnauthorizedInterceptor).toBeDefined();
    });

    describe('HTTP status', function() {
      describe('is 200 OK', function() {
        it('should return a 200 status', function() {
          $httpBackend.expectGET('http://api.domain.com/clients').respond(200, {});
          $http.get('http://api.domain.com/clients');
          $httpBackend.flush();
        });
      });

      describe('is 401 Unauthorized', function() {
        it('should redirect to accounts.domain.com', inject(function($window) {
          $httpBackend.expectGET('http://api.domain.com/clients').respond(401, {});
          $http.get('http://api.domain.com/clients');
          expect($window.location.href).toEqual('http://accounts.domain.com/oauth/.....');
          $httpBackend.flush();
        }));
      });
    });
  });
});

У меня есть: Expected 'http://localhost:8080/context.html' to equal 'http://accounts.domain.com/oauth/.....'. Любая помощь в том, как правильно издеваться над объектом $window или, в общем, как проверить случай переадресации 401 +?

4b9b3361

Ответ 1

Вы должны структурировать определение перехватчика, используя более свежий синтаксис. Ваша структура URL также должна быть в службе, чтобы ее можно было легко высмеять в тестах.

.factory('UnauthorizedInterceptor', function($q, $window, OtherService) {
  var service = {
    responseError: handleUnauthorized
  };

  return service;

  function handleUnauthorized(rejection) {
    if (rejection.status === 401) {
      $window.location.href = OtherService.getUnauthorizedRedirectURL();
    }
    return $q.reject(rejection);
  }
});

Таким образом, вы можете протестировать его так же, как и любой другой factory, не беспокоясь о внутренних реализациях перехватчиков $http или обманывая ответы с помощью $httpBackend.

describe('Domain.handlers.response', function() {
  var $window,
      UnauthorizedInterceptor,
      OtherService,
      redirectUrl = 'someUrl';

  beforeEach(module('Domain.handlers'));

  beforeEach(function () {
    $window = { location: { href: null } };

    module(function($provide) {
      $provide.value('$window', $window);
    });
  });

  beforeEach(inject(function(_UnauthorizedInterceptor_, _OtherService_) {
    UnauthorizedInterceptor = _UnauthorizedInterceptor_;
    OtherService = _OtherService_;

    spyOn(OtherService, 'getUnauthorizedRedirectURL').andReturn(redirectUrl);
  }));

  describe('UnauthorizedInterceptor', function() {
    it('should be defined', function() {
      expect(UnauthorizedInterceptor).toBeDefined();
    });

    it('should have a handler for responseError', function () {
      expect(angular.isFunction(UnauthorizedInterceptor.responseError)).toBe(true);
    });

    describe('when HTTP 401', function () {
      beforeEach(function () {
        var rejection = { status: 401 };
        UnauthorizedInterceptor.responseError(rejection);
      });

      it('should set window location', function () {
        expect($window.location.href).toBe(redirectUrl);
      });
    });

    describe('when not HTTP 401', function () {
      beforeEach(function () {
        var rejection = { status: 500 };
        UnauthorizedInterceptor.responseError(rejection);
      });

      it('should not set window location', function () {
        expect($window.location.href).not.toBe(redirectUrl);
      });
    });
  });
});

Ответ 2

Вот пример перехватчика responseError и соответствующей спецификации жасмина.

angular.module('interceptorDemo').factory('redirectInterceptor', ['$q', '$window', function($q, $window) {
    'use strict';

    function handleUnauthorizedAccess(config) {
        if (401 === config.status) {
            $window.location = '/signIn/';
        }
        return $q.reject(config);
    }

    return {
        responseError: handleUnauthorizedAccess
    };
}]);

Перехватчик перехватывает запрос ajax, если запрос не выполнен, тогда, если код состояния равен 401, тогда пользователь перенаправляется на страницу signIn.

Спецификация Жасмина для того же:

describe('redirectInterceptor specs', function() {

    var redirectInterceptor, $q;

    beforeEach(module('interceptorDemo'));

    beforeEach(function() {
        $window = {
            location: {
                href: null
            }
        };

        module(function($provide) {
            $provide.value('$window', $window);
        });
    });

    beforeEach(inject(function(_redirectInterceptor_, _$q_) {
        redirectInterceptor = _redirectInterceptor_;
        $q = _$q_;
        spyOn($q, 'reject');
    }));

    describe('redirectInterceptor specs', function() {
        it('should redirect to signIn page for unauthorized access', function() {
            var response = {
                status: 401,
                config: {}
            };
            var promise = redirectInterceptor.responseError(response);
            expect($window.location).toBe('/singIn/');
            expect($q.reject).toHaveBeenCalled();
        });

        it('should not redirect to signIn page for error code other than unauthorized access', function() {
            var response = {
                status: 404,
                config: {}
            };
            var promise = redirectInterceptor.responseError(response);
            expect($window.location).toEqual({
                href: null
            });
            expect($q.reject).toHaveBeenCalled();
        });

    });
});

Мы следили за $q, поэтому мы также можем проверить, что отклонение вызывается для ошибки 401.