I'm testing a custom AngularJS directive using Karma + Jasmine and the ngHtml2JsPreprocessor
plugin in order to serve my directive template, but I don't understand why my directive seems to be unable to access to the template (the compiled element is empty).
I defined the templateUrl
in the directive this way:
templateUrl: 'templates/angular/mywidget.html'
my Karma config is the following (the relevant part of it):
basePath: '../../main/webapp/static/',
files: [
{pattern: 'libs/angular/angular.js', watch: false},
{pattern: 'libs/angular-resource/angular-resource.js', watch: false},
{pattern: 'libs/angular-mocks/angular-mocks.js', watch: false},
{pattern: 'libs/angular-ngkit/js/ngkit.js', watch: false},
{pattern: 'libs/jquery/dist/jquery.js', watch: false},
'templates/angular/*.html',
'js/angular/**/*.js',
'../../../test/js/spec/angular/*.js'
],
preprocessors: {
'templates/angular/*.html': ['ng-html2js']
},
ngHtml2JsPreprocessor: {
moduleName: 'templates'
},
browsers: [
'PhantomJS'
],
plugins: [
'karma-phantomjs-launcher',
'karma-jasmine',
'karma-ng-html2js-preprocessor'
],
and in my test:
beforeEach(module('templates'));
beforeEach(module('ngResource'));
beforeEach(module('mywidget'));
the "funny" part is that if I test the template cache, the templates gets loaded and compiled:
beforeEach(inject(function(_$templateCache_) {
var template = _$templateCache_.get('templates/angular/mywidget.html');
}));
template exists! Why my directive can't use it? (in the browser it works perfectly).
If I replace templateUrl
with an inline template
in my directive, it gets rendered properly in the test... but I have to use an external template, is not acceptable to put it inline... I'm stuck!! Any smart idea?
UPDATE (what I've tried so far):
write a new directive with no logic (to exclude that the problem was in the implementation), simply:
angular.module('modulename', []).
directive('foo', function() {
return {
templateUrl: 'path/to/template.html'
}
});
simplify the template content to:
<div>hello world</div>
change the template path
change the template name
change the location of karma config file
removes extra dependencies like "ngResource" and similar
reinstalling all the bower dependencies (and cleaning the cache)
reinstalling all the npm packages
run tests from the command line (I was running test in Intellij Idea using the Karma plugin)
Pounding my fists against the desk while throwing a Fibonacci sequences of blasphemies that would have killed the pope if he had listened to it!
(the latest one usually brings me to the solution... but not this time)
UPDATE 2:
I bypassed the problem by defining my directive in this way:
directive('mywidget', function($templateCache) {
var config = {}; // directive definition (where you define "link", "restrict"...)
var templateUrl = 'templates/angular/mywidget.html';
var cachedTemplate = $templateCache.get(templateUrl);
if (cache) {
config.template = cachedTemplate;
}
else {
config.templateUrl = templateUrl;
}
return config;
});
By using this trick, my directive get rendered properly in tests. A this point it sounds a bug in AngularJS... it fails somehow to load the template from the cache. I'm really disappointed :(
YEAAAAAAAAAAH!!! I finally solved this crazy issue!!! The problem was that I was using different versions of angular dependecies (angular-mocks, angular-resource...) it turned out that If you are using, let's say, angular 1.2.27, then you MUST also be sure to use angular-mocks 1.2.27, angular-resource 1.2.27 and so on because otherwise there may be conflicts like the one I faced. Of course it wasn't my intention to use different versions, but somehow by installing my dependencies via bower I get these libraries "unaligned".
Try appending the compiled element to the document body with
angular.element(document.body).append(element);
You can put it in a beforeEach block:
beforeEach(function() {
inject(function(_$compile_, _$rootScope_) {
var compile, element, rootScope, scope;
compile = _$compile_;
rootScope = _$rootScope_;
scope = rootScope;
element = angular.element('<hello-directive></hello-directive>');
compile(element)(scope);
angular.element(document.body).append(element);
scope.$apply();
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With