我在为一些Angular指令编写单元测试时遇到了麻烦。特别是那些在指令中使用jQuery的人。我已经设计了一个简单的例子来说明我的问题。
这个愚蠢的指令将click事件绑定到元素。单击时,它会隐藏元素。 According to Angular,传递给指令的元素将被包装为jQuery元素。如果jQuery可用,它将使用jQuery,否则它将使用Angular的jQuery Lite。实际上,如果我在包含jQuery的浏览器中使用此指令,该指令将起作用并将隐藏单击的元素。
angular.module('myApp').directive('clickhide', function() { return {
link: function(scope, element, attrs) {
element.bind('click', function(e) {
element.hide();
scope.$digest();
});
}
}});
以下是该指令的Karma单元测试规范:
describe('clickhide', function() {
var scope, elm;
beforeEach(module('MyApp'));
beforeEach(inject(function($rootScope, $compile) {
scope = $rootScope;
elm = angular.element('<div clickhide></div>');
$compile(elm)(scope);
scope.$digest();
}));
it('should do a click', function() {
elm[0].click();
//OOPS: undefined is not a function error
expect($(elm).find(":hidden").length).toBe(1);
});
});
当我运行这个测试时,它失败并出现“undefined is not a function”的错误,意味着没有加载jQuery而Angular使用了jQuery Lite,而没有定义hide()。
我找到了解决这个问题的两种方法。
不要使用jQuery。需要重写我不想做的指令。
在我的指令中明确地包装元素以使它们成为jQuery元素:$(element).hide()
。还需要修改我的指令,我不想这样做。如果没有其他选择,我当然可以这样做。
我觉得应该可以让Angular在指令中自动使用jQuery,就像在Web浏览器中使用单元测试一样。我认为关键点在于Angular文档中的这一行:
要使用jQuery,只需在DOMContentLoaded事件触发之前加载它。
当运行单元测试时DOMContentLoaded发生时,我不清楚。我的Karma配置文件包含jQuery作为第一个文件,在angular之前:
module.exports = function(config) {
config.set({
basePath: '../../',
frameworks: ['jasmine', 'ng-scenario'],
files: [
'app/bower_components/jquery/dist/jquery.min.js',
'app/bower_components/angular/angular.js',
'app/bower_components/angular-route/angular-route.js',
'app/bower_components/angular-sanitize/angular-sanitize.js',
'app/bower_components/angular-mocks/angular-mocks.js',
...
],
exclude: [],
reporters: ['progress'],
port: 9876,
runnerPort: 9100,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
captureTimeout: 60000,
singleRun: false
});
};
我是否需要将jQuery注入测试?也许这是Karma的限制?有人知道吗?
答案 0 :(得分:2)
尝试在每个测试块之前覆盖$ in。
beforeEach(function() {
$.fn.hide = function() {
this.css( "display", "none" )
};
});
答案 1 :(得分:0)
我能够通过在angular之前加载jquery来解决类似的问题。 同样,如果$对您而言失败,则始终可以使用angular.element('')代替$