2014-11-22 3 views
12

응답 인터셉터를 테스트하려고하는데 $ 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); 
    }; 
}); 

그리고 내 사양입니다 : Expected 'http://localhost:8080/context.html' to equal 'http://accounts.domain.com/oauth/.....' :

'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(); 
     })); 
     }); 
    }); 
    }); 
}); 

내가있어 여기 내 인터셉터 코드입니다. 제대로 $ 윈도우 객체를 조롱하는 방법에 대한 도움말이나 일반적으로 401 + 리디렉션 사례를 테스트하는 방법에 대한 도움이 필요하십니까?

답변

14

more recent syntax을 사용하여 인터셉터 정의를 구성해야합니다. 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); 
    } 
}); 

이렇게하면 당신은 $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); 
     }); 
    }); 
    }); 
}); 
+1

답변 해 주셔서 감사합니다. 그것은 내가 모르는 것들을 이해하는데 많은 도움이되었습니다. 그러나 'http : // localhost : 8080/context.html'이 'http : //dev-accounts.domain.dev : 3000/oauth/authorize ...'가 될 때까지 동일한 오류가 발생합니다. 이것은'$ window.location.href'와 관련이 있다고 생각합니다. 어떻게 든 항상 http : // localhost : 8080/context.html을 반환합니다. 어떤 아이디어? – lkartono

+0

테스트를 실행중인 브라우저는 무엇입니까? – user2943490

+0

PhantomJs를 사용하고 있습니다. – lkartono

4

다음은 responseError 인터셉터 및 해당 jasmine 사양의 예입니다.

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 
    }; 
}]); 

인터셉터는 요청이 실패하면, 상태 코드 (401) 다음 사용자가 로그인 페이지로 리디렉션되는 경우, 아약스 요청을 차단합니다. 같은 대한

재스민 사양은 다음과 같습니다 우리는 $ q를 염탐 한

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(); 
     }); 

    }); 
}); 

그래서 우리는 또한이 401 오류에 대해 호출 거부하는지 테스트 할 수 있습니다.

관련 문제