最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Test Angular $window.location.href in Karma - Stack Overflow

programmeradmin5浏览0评论

I am trying to figure out how to properly inject the $window service into my angular controller, and then test to make sure it redirects appropriately. Currently, I am getting an error stating undefined is not a constructor (evaluating 'expect(window.location.href).toEqual('/profile')'). A snippet of my angular controller is as follows:

login.submitLogin = function(){
    LoginFactory.loginUser(login.dataset)
        .then(function(response){
            $window.location.href = '/profile'
        },function(response) {
            login.errorMessage = response.data.message;
        });
};

My unit test in Karma is as follows:

describe('Login Controller', function() {

    var controller, window;

    beforeEach(angular.mock.module('app'));

    beforeEach(inject(function(_$controller_, _$window_){
        window = _$window_;
        controller = _$controller_('LoginCtrl',window);
    }));

    describe('Login', function() {

        it('expects controller to be defined', function(){
            expect(controller).to.be.defined;
        });

        it('expects to be redirected after login', function() {
            controller.dataset.username = 'username';
            controller.dataset.password = 'password';
            controller.submitLogin();
            expect(window.location.href).toEqual('/profile');
        });
    });
});

I am trying to figure out how to properly inject the $window service into my angular controller, and then test to make sure it redirects appropriately. Currently, I am getting an error stating undefined is not a constructor (evaluating 'expect(window.location.href).toEqual('/profile')'). A snippet of my angular controller is as follows:

login.submitLogin = function(){
    LoginFactory.loginUser(login.dataset)
        .then(function(response){
            $window.location.href = '/profile'
        },function(response) {
            login.errorMessage = response.data.message;
        });
};

My unit test in Karma is as follows:

describe('Login Controller', function() {

    var controller, window;

    beforeEach(angular.mock.module('app'));

    beforeEach(inject(function(_$controller_, _$window_){
        window = _$window_;
        controller = _$controller_('LoginCtrl',window);
    }));

    describe('Login', function() {

        it('expects controller to be defined', function(){
            expect(controller).to.be.defined;
        });

        it('expects to be redirected after login', function() {
            controller.dataset.username = 'username';
            controller.dataset.password = 'password';
            controller.submitLogin();
            expect(window.location.href).toEqual('/profile');
        });
    });
});
Share Improve this question asked Aug 11, 2016 at 14:07 unseen_damageunseen_damage 1,3762 gold badges15 silver badges32 bronze badges 5
  • The correct syntax is _$controller_('LoginCtrl', { $window: window }). And mocked $window service can be supplied to controller instead of window this way. – Estus Flask Commented Aug 11, 2016 at 15:05
  • I changed my code to the following : $window = _$window_; controller = _$controller_('LoginCtrl', { $window: window }); in the beforeEach. I injected expect($window.location.href).toEqual('/profile') and still get the exception. Do I need to mock the backend as Andrzej suggested? – unseen_damage Commented Aug 11, 2016 at 15:14
  • { $window: window } doesn't make sense because it is already equal to window. You need to stub $window with { location: {} } object to not let the controller screw up window global, this is what it is about. If LoginFactory does http request then sure, you need to mock it, too. The preferable way to do unit tests to mock everything but tested unit (including LoginFactory). – Estus Flask Commented Aug 11, 2016 at 15:20
  • So do you mean to say it should look like this?: controller = _$controller_('LoginCtrl', {location: {} }); and then in the expect: expect(window.location.href).toEqual('/profile'); – unseen_damage Commented Aug 11, 2016 at 15:37
  • Real $window shouldn't be injected at all in this case, it is just not needed. You mock it with $windowMock = ...; _$controller_('LoginCtrl', { $window: $windowMock }) and then expect on $windowMock.location.href. – Estus Flask Commented Aug 11, 2016 at 15:42
Add a ment  | 

1 Answer 1

Reset to default 5

One solution is just mock (overwrite) $window service in your tests:

    beforeEach(function () {
        module(function($provide) {
            $provide.value('$window', {
                location: {href: ''}
            });
        });
    });

    beforeEach(inject(function(_$controller_, _$window_){
        window = _$window_;
        controller = _$controller_('LoginCtrl',window);
    }));

and then just check what has been assigned to $window.location.href by:

expect(window.location.href).toEqual('/profile');

also you need to use $httpBackend if LoginFactory.loginUser makes request to server:

    it('expects to be redirected after login', function() {
        var mockedResponse = {};

        controller.dataset.username = 'username';
        controller.dataset.password = 'password';

        $httpBackend.whenPOST('/api/login/').respond(mockedResponse);
        controller.submitLogin();
        $httpBackend.flush();

        expect(window.location.href).toEqual('/profile');
    });
发布评论

评论列表(0)

  1. 暂无评论