AngularJS测试指令与Karma,Jasmine和ngHtml2JsPreprocessor:模板未加载

时间:2014-11-25 09:48:42

标签: angularjs jasmine karma-runner karma-jasmine

我正在使用Karma + Jasmine和ngHtml2JsPreprocessor插件测试自定义AngularJS指令,以便为我的指令模板提供服务,但我不明白为什么我的指令似乎无法访问模板(编译的元素是空的)。 我用这种方式在指令中定义了templateUrl

templateUrl: 'templates/angular/mywidget.html'

我的Karma配置如下(相关部分):

        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'
        ],

在我的测试中:

beforeEach(module('templates'));
beforeEach(module('ngResource'));
beforeEach(module('mywidget'));

“有趣”部分是,如果我测试模板缓存,模板将被加载和编译:

beforeEach(inject(function(_$templateCache_) {
    var template = _$templateCache_.get('templates/angular/mywidget.html');
}));

模板存在!为什么我的指令不能使用它? (在浏览器中它完美地工作)。 如果我在我的指令中使用内联templateUrl替换template,它会在测试中正确呈现...但我必须使用外部模板,不能接受将其内联...我被卡住!!有什么好主意吗?

更新(我到目前为止尝试过的):

  1. 编写一个没有逻辑的新指令(以排除问题出现在实现中),简单地说:

    angular.module('modulename', []). directive('foo', function() { return { templateUrl: 'path/to/template.html' } });

  2. 将模板内容简化为:

    <div>hello world</div>

  3. 更改模板路径

  4. 更改模板名称

  5. 更改karma配置文件的位置

  6. 删除了额外的依赖项,例如“ngResource”和类似的

  7. 重新安装所有bower依赖项(并清理缓存)

  8. 重新安装所有npm软件包

  9. 从命令行运行测试(我使用Karma插件在Intellij Idea中运行测试)

  10. 将拳头砸在桌子上,同时抛出斐波那契一连串的亵渎神明,如果他听了就会杀死教皇!

  11. (最新的一个通常会带我到解决方案......但不是这次)

    更新2:

    我通过这种方式定义我的指令绕过了问题:

    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;
    });
    

    通过使用这个技巧,我的指令在测试中得到了正确的呈现。 这一点听起来像AngularJS中的一个错误...它以某种方式从缓存中加载模板失败。 我真的很失望:(

2 个答案:

答案 0 :(得分:5)

YEAAAAAAAAAAH !!! 我终于解决了这个疯狂的问题! 问题是我使用了不同版本的角度依赖(角度模拟,角度资源......),结果证明,如果你正在使用,那就说,角度为1.2.27,那么你必须也一定要使用角度模拟1.2.27,角度资源1.2.27等等,因为否则可能会出现类似我面临的冲突。 当然,我不打算使用不同的版本,但不知何故通过凉亭安装我的依赖项我得到了这些库&#34;未对齐&#34;。

答案 1 :(得分:1)

尝试使用

将已编译的元素附加到文档正文
angular.element(document.body).append(element);

您可以将它放在beforeEach块中:

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();
  });
});