Question

were using qunit in our team and I'm trying to figure out how to test directives with qunit. I'm following the example https://egghead.io/lessons/angularjs-unit-testing-a-directive

Here is the directive:

var app = angular.module("app", []);

app.directive("ehSimple", function() {
    return function(scope, element) {
        element.addClass("plain");
    }
})

And here is my qunit test so far

var injector = angular.injector(['ng', 'app']);

test('ehSimple directive', function() {

    var element;
    var $scope;

    injector.invoke(['$compile', function($compile, $rootScope) {
        $scope = $rootScope;
        element = angular.element('<div eh-simple>{{ 2 + 2}}</div>');
        $compile(element)($rootScope);
    }]);
    $scope.$digest();
    console.log(element.html());

    ok(element.html() == '4');
});

When I try to run the test with kara I get:

Died on test #1 @/home/.../tests/qunit/test_directives.js:34
: [ng:areq] Argument 'scope' is required

Very frustrating any ideas?

Was it helpful?

Solution

The issue you have is that you're not configuring your invoke function consistently in the injector invoke line. Your invoke() says that function takes a single argument $compile but the function definition expects two arguments $compile and $rootScope. Thus the $rootScope is undefined in the body of the function and you get a bizarro error down the track about scope being missing. Specifically, the invoke line should be:

injector.invoke(['$compile', '$rootScope', function($compile, $rootScope) { ... }]);

This is a common pattern in Angular function declaration and invocation - an alternative to it is:

injector.invoke(function($compile, $rootScope) { ... });

ie. without the wrapping array defining the arguments. This only works if you don't minify your code though. If you minify it, Angular can't introspect the function to determine the correct arguments to pass in, hence the array form which explicitly lists the argument names.

See the $injector docs on function annotation for (slightly) more info.

Note that the test could be written far more simply by avoiding the unnecessary invoke():

test('ehSimple directive', function() {
    var element;
    var $scope = injector.get('$rootScope');
    var $compile = injector.get('$compile');

    element = angular.element('<div eh-simple>{{ 2 + 2}}</div>');
    $compile(element)($scope);
    $scope.$digest();
    console.log(element.html());

    ok(element.html() == '4');
});

Since all the invoke() is doing for you is a bunch of injector.get() and calling your function with the results.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top