我想为AngularJS指令编写一个Jasmine单元测试。该指令简单地将contextmenu事件处理函数绑定到元素:
var myDirectives = angular.module('myApp.directives', []);
myDirectives.directive('myRightClick', ['$parse', function ($parse) {
return function (scope, element, attrs) {
var fn = $parse(attrs.myRightClick);
element.bind('contextmenu', function (event) {
scope.$apply(function () {
event.preventDefault();
fn(scope, { $event: event });
});
});
};
}]);
<div my-right-click="myFunction"></div>
单元测试:
describe('Unit Test Directives', function () {
var $compile;
var $rootScope;
beforeEach(module('myClientApp.directives'));
beforeEach(inject(function (_$compile_, _$rootScope_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
}));
it('should wire a contextmenu event binding for the element', function () {
// Compile a piece of HTML containing the directive
var element = $compile("<div my-right-click='myFunction'></div>")($rootScope)[0];
// Check that the compiled element contains the templated content
expect(element.attributes["my-right-click"].value).toEqual("myFunction");
expect(element.attributes["oncontextmenu"]).toNotEqual(undefined);
})
});
单元测试在最后一个断言上失败,因为元素oncontextmenu
属性未定义。但是,该指令正确地调用应用程序本身中的函数。如何在测试中确定函数已正确绑定到元素的oncontextmenu事件?
修改
或者,作为一种替代和更好的方法,我如何连接一个事件处理程序并通过测试中的指令调用它,以便我可以检查它实际上是否被调用?
答案 0 :(得分:10)
我刚才有同样的问题,这是我的解决方案......
使用triggerHandler分派事件,然后测试是否调用了提供的函数:
var called;
$rootScope.myFunction = function() {
called = true;
}
var element = $compile('<div my-right-click="myFunction"></div>')($rootScope);
element.triggerHandler('contextmenu');
expect(called).toEqual(true);
中号
答案 1 :(得分:2)
以下javascript函数将触发传递给它的JQueryLite元素的contextmenu事件:
//simulate user right-clicking on the element and check handler gets called
function fireContextMenuEvent(element) {
if (document.createEvent) {
var ev = document.createEvent('HTMLEvents');
ev.initEvent('contextmenu', true, false);
element.dispatchEvent(ev);
} else { // Internet Explorer
element.fireEvent('oncontextmenu');
}
}
答案 2 :(得分:1)
我选择了另一种方法。您可以使用指令在右键单击时绑定特定操作,使用contextmenu
事件:
app.directive('ngRightClick', function($parse) {
return function(scope, element, attrs) {
var fn = $parse(attrs.ngRightClick);
element.bind('contextmenu', function(event) {
scope.$apply(function() {
event.preventDefault();
fn(scope, {$event:event});
});
});
};
});