5

AngularJS ディレクティブの Jasmine 単体テストを作成したいと考えています。ディレクティブは、コンテキスト メニュー イベント ハンドラー関数を要素にバインドするだけです。

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 イベントに正しくバインドされていることをテストで確認するにはどうすればよいですか?

編集

または、代替のより良いアプローチとして、イベント ハンドラーを接続し、テストのディレクティブを介して呼び出して、実際に呼び出されることを確認するにはどうすればよいでしょうか?

4

3 に答える 3

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);

M

于 2013-12-19T15:00:01.343 に答える
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});
            });
        });
    };
});

JSFiddle のコード例

于 2013-07-18T11:43:11.473 に答える