Unit testing 单元测试角度右键单击指令

Unit testing 单元测试角度右键单击指令,unit-testing,angularjs,angularjs-directive,jasmine,Unit Testing,Angularjs,Angularjs Directive,Jasmine,我想为AngularJS指令编写一个Jasmine单元测试。该指令仅将contextmenu事件处理程序函数绑定到元素: var myDirectives = angular.module('myApp.directives', []); myDirectives.directive('myRightClick', ['$parse', function ($parse) { return function (scope, element, attrs) { var f

我想为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>
var myDirectives=angular.module('myApp.directives',[]);
指令('myRightClick',['$parse',函数($parse){
返回函数(范围、元素、属性){
var fn=$parse(attrs.myRightClick);
元素绑定('contextmenu',函数(事件){
作用域:$apply(函数(){
event.preventDefault();
fn(作用域,{$event:event});
});
});
};
}]);
单元测试:

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);
    })
});
description('单元测试指令',函数(){
var$compile;
var$rootScope;
在每个模块之前(模块('myClientApp.directives');
beforeach(注入函数($compile,$rootScope){
$compile=\$compile;
$rootScope=\u$rootScope;
}));
它('应该为元素,'函数()连接contextmenu事件绑定){
//编译一段包含指令的HTML
var元素=$compile(“”($rootScope)[0];
//检查编译的元素是否包含模板化的内容
expect(element.attributes[“我的右键单击”].value).toEqual(“我的函数”);
expect(element.attributes[“oncontextmenu”]).toNotEqual(未定义);
})
});
单元测试在最后一次断言中失败,因为元素
oncontextmenu
属性未定义。但是,该指令正确地调用了应用程序本身中的函数。如何在测试中确定函数已正确绑定到元素的oncontextmenu事件

编辑


或者,作为一种更好的替代方法,我如何连接事件处理程序并通过测试中的指令调用它,以便检查它是否实际被调用?

我选择了一种替代方法。使用
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});
            });
        });
    };
});

以下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');
    }
}

我刚刚遇到了完全相同的问题,这是我的解决方案

用于分派事件,然后测试是否调用了提供的函数:

var called;
$rootScope.myFunction = function() {
    called = true;
}

var element = $compile('<div my-right-click="myFunction"></div>')($rootScope);
element.triggerHandler('contextmenu');
expect(called).toEqual(true);
var调用;
$rootScope.myFunction=function(){
调用=真;
}
var元素=$compile(“”)($rootScope);
元素triggerHandler('contextmenu');
expect(调用)。toEqual(true);

的确如此。如果你看一下“我的问题”中的指令代码,你会发现它与你的指令代码完全相同!但问题是如何测试它:特别是如何在单元测试中绑定事件处理程序并通过指令调用它。