Micah Bolen
Micah Bolen

Reputation: 151

Why is this Angular directive not compiling inside of Jasmine unit test?

Preconditions: I am using Karma to run Jasmine unit tests against my Angular.js app modules.

My app uses the following pattern to expose modules (services/directives/controllers):

simple.js

'use strict';

export default (angular) => {
    angular.module('simple', [])
        .directive('simple', [function() {
            return {
                restrict: 'E',
                replace: true,
                template: '<h1>COMPILED!</h1>'
            };
        }]);
};

The corresponding unit test for the above example looks like this:

simple.test.js

import angular from 'angular';
import mocks from 'angular-mocks';
import simpleModule from './simple';

describe('simple', () => {
    var $compile,
        $rootScope;

    // Load the simple module, which contains the directive
    beforeEach(() => {
        let simpleComponent = new simpleModule(angular);
        // module('simple') raises a TypeError here
        // I have also tried angular.module('simple') which
        // I am pretty sure is incorrect.
    });

    // Store references to $rootScope and $compile
    // so they are available to all tests in this describe block
    beforeEach(inject((_$compile_, _$rootScope_) => {
        // The injector unwraps the underscores (_) from around the
        // parameter names when matching
        $compile = _$compile_;
        $rootScope = _$rootScope_;
    }));

    it('Replaces the element with the appropriate content', () => {
        // Compile a piece of HTML containing the directive
        var element = angular.element("<simple>not compiled</simple>");

        var compiledElement = $compile(element)($rootScope);

        // fire all the watches, so the scope expressions evaluate
        $rootScope.$digest();

        // Check that the compiled element contains the templated content
        expect(element.html()).toContain("COMPILED!");

    });

});

Problem: when running the above test with Karma in a web browser, the test fails and the element does not appear to be getting compiled.

What am I missing?

Upvotes: 5

Views: 2477

Answers (3)

bySamo
bySamo

Reputation: 475

I can see in your code that you are missing the creation of the new $scope before do the $compile. You should do something like this:

it('Replaces the element with the appropriate content', () => {
    // Compile a piece of HTML containing the directive
    var scope = $rootScope.$new(); // create a new scope
    var element = angular.element("<simple>not compiled</simple>");
    var compiledElement = $compile(element)(scope);

    // fire all the watches, so the scope expressions evaluate
    scope.$digest();

    // Check that the compiled element contains the templated content
    expect(element.html()).toContain("COMPILED!");
});

Upvotes: 2

Wilmer SH
Wilmer SH

Reputation: 1417

The obvious is that you are using Javascript ES6 in your tests. Jasmine only understands ES5 as of now.

Try using this Jasmine ES6 Compiler, or write your tests in ES5.

Note: That your tests are not being compiled but they fail seems contradictory. They can only fail if karma attempts to run them. And they can only run if they are compiled. Are you sure about this?

Upvotes: 0

user367766
user367766

Reputation: 31

I suspect you are not importing the directive correctly. Have you tried:

beforeEach(module('simple'));

The alternate version you indicated you tried are not correct or are patterns I have not seen:

beforeEach(() => {
    let simpleComponent = new simpleModule(angular);
});

module('simple');

angular.module('simple');

Upvotes: 0

Related Questions