Unit test angular right-click directive

angularjs, angularjs-directive, jasmine, unit-testing

Solution

The following javascript function will fire the contextmenu event on the JQueryLite element passed to it:

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

Problem

I want to write a Jasmine unit test for an AngularJS directive. The directive simply binds a contextmenu event handler function to the element: ``` 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> ``` Unit test: ``` 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); }) }); ``` The unit test fails on the last assertion, because the element `oncontextmenu` attribute is undefined. However, the directive correctly invokes the function in the application itself. How can I determine in a test that a function has been correctly bound to the element's oncontextmenu event? Edit Or, as an alternative and better approach, how can I wire up an event handler and invoke it via the directive in the test so that I can check that it actually gets called?

Original source