1

I am using the npm module karma-ng-html2js-preprocessor to do this.

My spec file is:

describe('Directive: aGreatEye (external)', function() {
    var elm, scope;

    beforeEach(module('my-thing.template.html'));
    beforeEach(module('templates'));

    beforeEach(inject(function($rootScope, $compile) {

        elm = angular.element('<a-great-eye></a-great-eye>');
        scope = $rootScope;
        $compile(elm)(scope);
        scope.$digest();
    }));

    it('should do first directive unit test properly', function() {
        // assertions here
    });
});

and yet my error is Error: [$injector:modulerr] Failed to instantiate module my-thing.template.html due to: Error: [$injector:nomod] Module 'my-thing.template.html' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.

Despite the url being correct from where the basePath of the karma.config.js file is.

Here is my karma.config.js file:

module.exports = function (config) {

    // VIEW ONLINE AT: MAIN_ROOT/tests/jasmineReport/
    // You can either run via WebStorm or go online to do tests

    config.set({
        basePath: '.',
        frameworks: ['jasmine'],
        files: [
            // Vendor Files
            'bower_components/angular/angular.js',
            'bower_components/angular-mocks/angular-mocks.js',
            'bower_components/angular-ui-router/release/angular-ui-router.js',
            'bower_components/angular-filter/dist/angular-filter.js',
            'bower_components/angular-sanitize/angular-sanitize.js',
            'bower_components/lodash/lodash.min.js',

            // App-Specific Files
            'app/index.js',
            'app/common/models/*.js',
            'app/common/directives/*.js',
            'app/common/filters/*.js',
            'app/main/main.js',

            // App-Specific HTML Templates
            '*.html',
            '*.html.ext',

            // Test-Specific Files
            'tests/mock/**/*.js'
        ],
        exclude: [],
        preprocessors: {

            // HTML to JavaScript Preprocessors for
            // AngularJS Template Directives
            '*.html': ['ng-html2js']

        },
        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        browsers: ['PhantomJS'],
        singleRun: true,
        concurrency: Infinity,

        // NgHTML 2 JS Pre-Processor - OPTIONS
        ngHtml2JsPreprocessor: {
            stripPrefix: 'public/',
            stripSuffix: '.ext',
            prependPrefix: 'served/',
            moduleName: "templates"
        }
    })
};

What am I doing wrong?

2
  • why don't you inject the template with a mock? I never used ngHtml2JsPreprocessor, I can understand that this should be done by that, but it seems to me overcomplicated... Commented Dec 10, 2015 at 18:47
  • Can you point me to the right direction? I tried search the google. Commented Dec 10, 2015 at 19:12

1 Answer 1

1

these are my test for my directive, they test if the template is called correctly and elaborated correctly:

'use strict';

/**
* @author Gianmarco Laggia
* 
* Test suite for menu directive
*/
describe('Menu Widget Directive Rendering', function () {

    beforeEach(module('myModule'));

    var compile, mockBackend, rootScope;

    // Step 1 - Get the $compile service injected into our test
    beforeEach(inject(function ($compile, $httpBackend, $rootScope) {
        compile = $compile;
        mockBackend = $httpBackend;
        rootScope = $rootScope;
    }));


    it('should render HTML based on scope correctly', function () {
        var scope = rootScope.$new();

        mockBackend.expectGET('views/directives/menu.html').respond(
            '<div class="menu">' +
            '<ul>' +
            '<li><a href="#/" class="waves-effect waves-light">HOME</a></li>' +
            '<li><a href="#/activities" class="waves-effect waves-light">ATTIVIT</a></li>' +
            '<li><a href="#/people" class="waves-effect waves-light">PERSONE</a></li>' +
            '<li><a href="#/locations" class="waves-effect waves-light">LUOGHI</a></li>' +
            '<div class="clear-both"></div>' +
            '</ul>' +
            '</div>');

        //Step 4
        var element = compile('<menu></menu>')(scope);

        //Step 5
        scope.$digest();
        mockBackend.flush();

        //Step 6
        expect(element.html()).toEqual(
            '<div class="menu">' +
            '<ul>' +
            '<li><a href="#/" class="waves-effect waves-light">HOME</a></li>' +
            '<li><a href="#/activities" class="waves-effect waves-light">ATTIVIT</a></li>' +
            '<li><a href="#/people" class="waves-effect waves-light">PERSONE</a></li>' +
            '<li><a href="#/locations" class="waves-effect waves-light">LUOGHI</a></li>' +
            '<div class="clear-both"></div>' +
            '</ul>' +
            '</div>'
        );
        mockBackend.verifyNoOutstandingExpectation();
    });

    it('should not render HTML is used not as element 1', function () {
        //Step 2 - Set up our directive instance HTML
        var scope = rootScope.$new();

        //Step 4
        var element = compile('<div menu></div>')(scope);

        //Step 5
        scope.$digest();

        //Step 6
        expect(element.html()).toEqual('');
        mockBackend.verifyNoOutstandingRequest();
    });

    it('should not render HTML is used not as element 2', function () {
        //Step 2 - Set up our directive instance HTML
        var scope = rootScope.$new();

        //Step 4
        var element = compile('<div class="menu"></div>')(scope);

        //Step 5
        scope.$digest();

        //Step 6
        expect(element.html()).toEqual('');
        mockBackend.verifyNoOutstandingRequest();
    });

    it('should not render HTML is used not as element 3', function () {
        //Step 2 - Set up our directive instance HTML
        var scope = rootScope.$new();

        //Step 4
        var element = compile('<!-- directive: menu -->')(scope);

        //Step 5
        scope.$digest();

        //Step 6
        expect(element.html()).toBeUndefined();
        mockBackend.verifyNoOutstandingRequest();
    });
});

This test that the directive is called only with <menu></menu> due to its restriction

/**
* @author Gianmarco Laggia
*
* Menu directive, used to handle a menu based on the actual $location.path
*/
angular.module('myModule')
    .directive('menu', ['Page', function (Page) {
        return {
            restrict: 'E',
            scope: true,
            templateUrl: 'views/directives/menu.html',
            link: function ($scope, $element, $attrs) {
                $scope.isCurrentPage = function (page) {
                    return Page.getActualPage() == page;
                };
            }
        };
}]);
Sign up to request clarification or add additional context in comments.

7 Comments

The only thing I have a problem with is that you need to add your own response with your own data.. I with to grab the template instead of making your own response. But thank you.
I can't understand what you mean
In the line mockBackend.expectGET('views/directives/menu.html').respond( you are telling the code what to get back as data when I really want the template.html to be inserted in there
in my opinion it's a bad practis to have unit tests that depends on external resources. The thing is that is unnecessary to pass the directive the actual file, the reason is that if that file change you will never be able to assert on it (the assertion is hardcoded)
I am not sure I follow. I mean. I think I got it but the last part got to me. So are you saying that I should unit test my directives with inline templates?
|

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.