在我的karma.conf.coffee
中,我有:
files: [
'public/bower_components/angular-mocks/angular-mocks.js'
'public/scripts/**/*.coffee' # not tested since configuration is difficult to be tested and perhaps should not be tested
'test/webapp/unit/**/*.coffee'
'views/templates/*.html'
]
preprocessors:
'public/scripts/**/*.coffee': ['coverage']
'test/webapp/unit/**/*.coffee': ['coffee']
'views/templates/*.html': ['ng-html2js']
frameworks: ['jasmine']
ngHtml2JsPreprocessor:
stripPrefix: 'views/'
在我的测试中,我有:
describe('Directive: timespanSelector', function() {
var scope;
scope = null;
beforeEach(module('myApp'));
beforeEach(module('templates/partialDateRange.html'));
beforeEach(function() {
var html;
html = "<timespan-selector></timespan-selector>";
return inject(function($compile, $rootScope) {
var compiled, elem;
scope = $rootScope.$new();
elem = angular.element(html);
compiled = $compile(elem);
compiled(scope);
return scope.$digest();
});
});
return it('should test', function() {});
});
当我运行时,它说:
Error: [$injector:modulerr] Failed to instantiate module templates/partialDateRange.html due to:
Error: [$injector:nomod] Module 'templates/partialDateRange.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.
http://errors.angularjs.org/1.2.16/$injector/nomod?p0=templates%2FpartialDateRange.html
我做错了什么?
答案 0 :(得分:3)
这对我们来说已经有很长一段时间了,我花了几天时间才找到解决方案 - 这就是我们想出来的。我将简单介绍如何配置文件结构。
首先,您需要包含karma-ng-html2js-preprocessor。
npm install karma-ng-html2js-preprocessor --save-dev
接下来你的karma.conf.js - 你用咖啡但我不会反对你; - )
请记住包含模块名称,以便将其注入指令单元测试。
// Karma configuration
// http://karma-runner.github.io/0.10/config/configuration-file.html
module.exports = function (config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '',
// testing framework to use (jasmine/mocha/qunit/...)
frameworks: ['jasmine'],
preprocessors: {
'app/views/templates/*.tpl.html': ['ng-html2js'] //<----- Also needed
},
// list of files / patterns to load in the browser
files: [
'app/bower_components/angular/angular.js',
'app/bower_components/angular-mocks/angular-mocks.js',
'app/bower_components/angular-resource/angular-resource.js',
'app/bower_components/angular-cookies/angular-cookies.js',
'app/bower_components/angular-sanitize/angular-sanitize.js',
'app/bower_components/angular-bootstrap/ui-bootstrap.js',
'app/bower_components/angular-ui-router/release/angular-ui-router.js',
'app/bower_components/angular-local-storage/angular-local-storage.js',
'app/bower_components/jquery/dist/jquery.js',
'app/bower_components/bootstrap/dist/js/bootstrap.js',
'app/scripts/*.js',
'app/scripts/**/*.js',
'test/spec/**/*.js',
//Templates
'app/views/templates/*.tpl.html' //<----- Also needed
],
ngHtml2JsPreprocessor: {
stripPrefix: 'app/',
moduleName: 'Kinetix.Templates' //<-----Module Name for injection
},
// list of files / patterns to exclude
exclude: [],
// Reporters
reporters: ['progress', 'junit'],
//Config for junit
junitReporter: {
outputFile: './test/test-results.xml',
suite: ''
},
// web server port
port: 9001,
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false
});
};
那么在你得到你的karma.conf.js设置后,让我们看一下单元测试。这是一个指令单元测试我将包括整个事情 - 也许它可以激发你的其他单元测试的想法。我已经在这里待了将近8个月并且学到了很多......
指令单元测试:
'use strict';
describe('Directives: Search', function () {
var//iable declarations
elm,
scope,
$rootScope,
$compile,
$animate,
ACCESS_LEVEL = [
'OPEN',
'PRIVATE',
'RESTRICTED'
]
;
beforeEach(function () {
module('Kinetix.Constants');
module('Kinetix.Templates'); //<------ See here we inject the templates!
module('Kinetix.Directives.Search');
module('Kinetix.Controllers.Search', function ($controllerProvider) {
$controllerProvider.register('SearchController', function () { });
});
});
beforeEach(inject(function (_$rootScope_, _$compile_, _$animate_) {
$rootScope = _$rootScope_;
scope = $rootScope;
$animate = _$animate_;
$compile = _$compile_;
}));
function setupDirective(accessLevel) {
spyOn($animate, 'addClass').and.callThrough();
spyOn($animate, 'removeClass').and.callThrough();
$rootScope.accessLevel = { type: accessLevel };
$rootScope.isAuthenticated = { value: false };
elm = angular.element('<kx-search></kx-search>');
$compile(elm)(scope);
scope.$apply();
}
it('Should create the search template', function () {
setupDirective(ACCESS_LEVEL[0]);
var nav = $(elm).find('.nav');
expect(nav.children('form')).toBeTruthy();
});
describe('Animations', function () {
it('should have the fade slide class on setup with OPEN accesslevel', function () {
setupDirective(ACCESS_LEVEL[0]);
//With Authentication
$rootScope.isAuthenticated.value = true;
scope.$apply();
expect(elm.children('div').hasClass('slide-left')).toBeTruthy();
expect($animate.addClass).toHaveBeenCalled();
$rootScope.isAuthenticated.value = false;
scope.$apply();
expect($animate.removeClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('slide-left')).toBeFalsy();
});
it('should toggle the fade-slide animation with PRIVATE acesslevels', function () {
setupDirective(ACCESS_LEVEL[1]);
expect($animate.addClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeTruthy();
$rootScope.isAuthenticated.value = true;
scope.$apply();
expect($animate.removeClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeFalsy();
$rootScope.isAuthenticated.value = false;
scope.$apply();
expect($animate.addClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeTruthy();
});
it('should toggle the fade-slide animation with RESTRICTED acesslevels', function () {
setupDirective(ACCESS_LEVEL[2]);
expect($animate.addClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeTruthy();
$rootScope.isAuthenticated.value = true;
scope.$apply();
expect($animate.removeClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeFalsy();
$rootScope.isAuthenticated.value = false;
scope.$apply();
expect($animate.addClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeTruthy();
});
});
});
为了完成,我还将包含指令本身,以便您可以看到完整的图片。
angular.module('Kinetix.Directives.Search', [])
.directive('kxSearch', function ($rootScope, $animate, PATH) {
var linker = function (scope, el) {
var//iable declarations
accessLevel = $rootScope.accessLevel.type || 'Guest',
element = el.children('.nav')
;
//Check if the shop type is a PRIVATE or RESTRICTED type so we can chose which animation to apply
if (accessLevel === 'RESTRICTED' || accessLevel === 'PRIVATE') {
// Hide the element as we need authentication to show it
$animate.addClass(element, 'fade-slide');
$rootScope.$watch('isAuthenticated.value', function (newVal) {
if (!!newVal) {
$animate.removeClass(element, 'fade-slide');
}
if (!newVal) {
$animate.addClass(element, 'fade-slide');
}
});
}
if (accessLevel === 'OPEN') {
$rootScope.$watch('isAuthenticated.value', function (newVal, oldVal) {
if (newVal !== oldVal) {
if(!!newVal) {
$animate.addClass(element, 'slide-left');
}
if(!newVal) {
$animate.removeClass(element, 'slide-left');
}
}
});
}
};
return {
restrict: 'E',
link: linker,
controller: 'SearchController',
templateUrl: PATH.templates + 'search.tpl.html'
};
});
希望它有所帮助!这是房间里的800磅大猩猩已经有一段时间了,一旦你驯服了他,他就非常可爱!祝你好运!
答案 1 :(得分:1)
我做错了什么?
我知道这是因为你得到的错误:
Module 'templates/partialDateRange.html' is not available!
这是由以下代码行引起的:
beforeEach(module('templates/partialDateRange.html'));
ng-html2js
输出的位置。哪个是.js
文件。files
karma.conf.coffee
数组中包含该文件
.js
文件并查找angular.module('<module name>', [])
以确定ng-html2js
如何命名模块并使用您当前拥有'templates/partialDateRange.html'
的模块名称(它应该是类似的路径名称,如果不相同)。 答案 2 :(得分:-1)
karma-ng-html2js-preprocessor
的替代方案是grunt-angular-templates。但是,这假设您正在使用Grunt(还有一个gulp
版本浮动)。
将grunt-angular-templates
添加到package.json文件,然后从命令行运行grunt ngtemplates
。
这将连接整个应用程序中的所有模板(无论如何都使用templateURL
调用的模板),并将它们放在templates.js文件中。
然后你只需在karma.conf中包含这个文件就可以了。
设置karma-ng-html2js-preprocessor
时遇到了很多麻烦,因此,转向笨拙的任务是最快捷,最简单的方法。
希望你能尽快开始工作,无论你选择哪种方式。