ngHtml2JsPreprocessor does not load the module containing the templates, tested with karma

831 Views Asked by At

Testing my angular app with karma ngHtml2JsPreprocessor, I have read dozens of pages on how ton configure karma to generate js templates instead of html ones that are loaded by Angular Directives, I am stuck with the message :

Module 'js_templates' 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.
    http://errors.angularjs.org/1.4.6/$injector/nomod?p0=js_templates

My folder structure is like this :

/System/Root/Path/      
    web/
        js/ 
            app/
                test/
                    specs/
                        UserModule/
                            UserDirectives.spec.js
                modules/    
                    UserModule/ 
                        UserDirectives.js  <=== Where the directive is defined
        Templates
            login.tpl.html

My directive is defined like this :

directives.directive("loginForm", [function(){
return{
    restriction: "E",
    templateUrl: assetsRootPath+'/Templates/login.tpl.html' //assetsRootPath is defined to '' for karma
}]);

Karma is configured as follow :

module.exports = function(config) {
  config.set({

    basePath: './web/js/',
    frameworks: ['jasmine', 'requirejs'],
    preprocessors: {
      '../Templates/**/*.html': ['ng-html2js']
    },
    ngHtml2JsPreprocessor: {
      stripPrefix: '.*web/',
      prependPrefix: '/',
      moduleName: 'js_templates',
      enableRequireJs: false
    },
    plugins : [
      'karma-chrome-launcher',
      'karma-jasmine',
      'karma-requirejs',
      'karma-ng-html2js-preprocessor'
    ],

    // list of files / patterns to load in the browser
    files: [
      { pattern: '../Templates/**/*.html', included: false },
      //....Other needed files
    ]

The spec for testing the directive :

define(['angular', 'ngmocks', 'app/modules/UserModule/UserDirectives'], function() {
    describe("Test User Directive > ", function () {
        var $compiler, compiledElement;
        beforeEach(module('User.Directives'));
        beforeEach(module('js_templates'));

        beforeEach(inject(function (_$rootScope_, _$compile_) {
            $rootScope = _$rootScope_;
            $compile = _$compile_;
            scope = $rootScope.$new();
            compiledElement = $compile("<login-form></login-form>")(scope);
            scope.$digest();
        }));

        it('Tries to test', function(){
            expect(1).toEqual(1);
        });
    });
});

When I launch the tests the following error appears :

Module 'js_templates' 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.
    http://errors.angularjs.org/1.4.6/$injector/nomod?p0=js_templates

I have tried a lot of configurations and nothing works, I have also tried to debug ngHtml2JsPreprocessor by adding some log.debug & I see that the module 'js_templates' is rightly created, the problem is why can't I load it for the specs. Information that could be useful (not sure if it changes something) : I am working with requirejs. Thanks for your help

1

There are 1 best solutions below

0
On

Well, as no config worked, I have chosen to use a different approach, below is what I ended up to do to make it work :

1 - Remove all pre-processors 2 - Install the simple html2js node plugin : npm install karma-html2js-preprocessor --save-dev 3 - Inside my karma.conf file :

pattern: { files: '../Templates/**/*.html', included : true } //Note the included property to true
preprocessors: {
  '../Templates/**/*.html': ['html2js']
},

plugins : [
  'karma-chrome-launcher',
  'karma-jasmine',
  'karma-requirejs',
  'karma-html2js-preprocessor'
],

Inside my test-main.js file which is the entry point of require-js I have done this :

require([
        'angular',
        ...
    ], function(angular, app) {
        var $html = angular.element(document.getElementsByTagName('html')[0]);
        angular.element().ready(function() {
            // bootstrap the app manually
            angular.bootstrap(document, ['app']);

            //Making all templates to be availabe through js_template module
            angular.module('js_templates', []).run(function($templateCache){
                angular.forEach(window.__html__, function(content, filename){
                    var modifiedFilename = filename;
                    /*****************Modify this to fit your app**********************/
                    var breakPos = modifiedFilename.indexOf('/Templates');
                    modifiedFilename = filename.substr(breakPos, modifiedFilename.length - breakPos);
                    /*****************/Modify this to fit your app*********************/
                    $templateCache.put(modifiedFilename, content);
                });
            });
        });
    }
);

Not very sharp but not so bad as well, anyway it does work and it's exactly what I wanted. When a solution will come to work naturally with ngHtml2JsPreprocessor, I will use it.