0

I am trying to write a unit test for an AngularJS directive (which is wrapped in an module for requiring via requirejs), loading modules with requirejs, but I'm having issues with the global window object when loading in angular.

My current understanding is that I need to instantiate an angular app, add my directive to it, and then get the angular compiler to run on some HTML which contains the directive name. From that point on, I can test as usual.

However, when try to require angular in my test, I get the following error:

Uncaught Error: Evaluating c:\...\angular.js as module "angular" failed with error: ReferenceError: window is not defined

Some people suggested installing jsdom in order to get a window object, but from the error message above, you might be able to work out that I'm in a Windows environment and that combination seems to be painful.

At the moment, my test is simple:

// Imports, including requirejs config

describe("Directive tests", function() {
    var angular;
    before(function(done) {
        requirejs(['angular'], function(a) {
            angular = a;
        });
    });
});

I could go down the route of defining a window module in requirejs and have a mock version injected in the tests, but that seems like a lot of work.

2 Answers 2

1

The $window service is here for this purpose. Just inject it where needed.

From the documentation :

angular.module('windowExample', [])
    .controller('ExampleController', ['$scope', '$window', function($scope, $window) {
        $scope.greeting = 'Hello, World!';
        $scope.doGreeting = function(greeting) {
        $window.alert(greeting);
    };
}]);
Sign up to request clarification or add additional context in comments.

1 Comment

But this error is happening when try to require angular, I can't get as far as injecting a service. Angular is defined in the requirejs config map, so needs to be loaded as I have it above, doesn't it?
0

Unit tests should, by definition, test the unit in isolation from everything else. You should not need a window for it, or to require much of anything.

For example, here is a directive unit tests that launches a "confirm" popup. It uses mocha, but you could use jasmine or whatever you want.


    describe('confirm', function(){
        var element, scope, msg = "Are you sure?", html = 'ABC', spy, stub;
        beforeEach(function () {
            var self = this;
            stub = sinon.stub();
            self.$modal = {
                open: function () {
                    return {
                        result: {
                            then: stub
                        }
                    };
                }
            };
            spy = sinon.spy(self.$modal,"open");

            mod('GP.directives',{$modal:self.$modal});
            inject(function ($compile,$rootScope) {
                element = angular.element(html);
                scope = $rootScope;
                scope.foo = sinon.spy();
                $compile(element)(scope);
                scope.$digest();
                element.triggerHandler('click');
                scope.$digest();
            });
        });
        it('should call $modal.open when click the element', function(){
            spy.calledOnce.should.be.true;
        });
        it('should set up with "then"', function(){
            stub.calledOnce.should.be.true;
        });
        it('should have a single function argument to "then"', function(){
            stub.firstCall.args[0].should.be.type("function");
        });
        it('should not call the action when click the element', function(){
            scope.foo.called.should.be.false;
        });
    });

Notice that the only things the directive interacts with are:

  • $modal - OK, I stubbed that out
  • the html, which I passed in using $compile(angular.element(html))

This allows me to test it completely in isolation. It should be extremely rare that you actually need a window object to unit test something.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.